mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-07-09 17:29:12 +00:00
fix: clarify goal blocked audit guidance (#1481)
This commit is contained in:
parent
6c9abe8cf7
commit
131700097a
8 changed files with 80 additions and 22 deletions
5
.changeset/goal-blocked-audit-prompt.md
Normal file
5
.changeset/goal-blocked-audit-prompt.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@moonshot-ai/kimi-code": patch
|
||||
---
|
||||
|
||||
Tighten goal-mode guidance for blocked and complete status updates.
|
||||
|
|
@ -147,14 +147,24 @@ function buildGoalReminder(goal: GoalSnapshot): string {
|
|||
'after completing a useful slice, if material work remains, end the turn normally without ' +
|
||||
'calling UpdateGoal so the runtime can continue the goal in the next turn. Call UpdateGoal ' +
|
||||
'with `complete` only when all required work is done, any stated validation has passed, and ' +
|
||||
'there is no useful next action. Do not mark complete after only producing a plan, summary, ' +
|
||||
'first pass, or partial result. Before calling `complete`, check that every required part of ' +
|
||||
'the objective is done, completion criteria are satisfied, requested or expected validation ' +
|
||||
'passed or has been reported as impossible, and no known material task remains. Call ' +
|
||||
'UpdateGoal with `blocked` only for a genuine impasse: an external condition, required user ' +
|
||||
'input, missing credentials or permissions, a persistent technical failure, or an impossible, ' +
|
||||
'unsafe, or contradictory objective. Do not use `blocked` because the work is large, hard, ' +
|
||||
'slow, uncertain, partial, still needs validation, or needs more goal turns.',
|
||||
'there is no useful next action. Completion audit: before calling `complete`, verify the ' +
|
||||
'current state against the actual objective and every explicit requirement. Treat weak or ' +
|
||||
'indirect evidence as not complete. Do not mark complete after only producing a plan, ' +
|
||||
'summary, first pass, or partial result. Do not mark complete merely because a budget is ' +
|
||||
'nearly exhausted or you want to stop. Blocked audit: do not call UpdateGoal with `blocked` ' +
|
||||
'the first time you hit a blocker. Use `blocked` only for a genuine impasse: an external ' +
|
||||
'condition, required user input, missing credentials or permissions, or a persistent ' +
|
||||
'technical failure. For those non-terminal blockers, the same blocking condition must ' +
|
||||
'repeat for at least 3 consecutive goal turns before you call `blocked`, counting the ' +
|
||||
'original/user-triggered turn and automatic continuations. If a previously blocked goal is ' +
|
||||
'resumed, treat the resumed run as a fresh blocked audit. Exception: if the objective ' +
|
||||
'itself is impossible, unsafe, or contradictory, call UpdateGoal with `blocked` in the same ' +
|
||||
'turn; do not run more goal turns just to satisfy the audit. Do not use `blocked` because ' +
|
||||
'the work is large, hard, slow, uncertain, incomplete, still needs validation, would ' +
|
||||
'benefit from clarification, or needs more goal turns. Once the 3-turn threshold is met ' +
|
||||
'and you cannot make meaningful progress without user input or an external-state change, ' +
|
||||
'call UpdateGoal with `blocked`; do not keep reporting the blocker while leaving the goal ' +
|
||||
'active.',
|
||||
);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,15 +93,23 @@ const GOAL_CONTINUATION_PROMPT = [
|
|||
'useful slice, if material work remains, end the turn normally without calling UpdateGoal so',
|
||||
'the runtime can continue the goal in the next turn. Call UpdateGoal with `complete` only when',
|
||||
'all required work is done, any stated validation has passed, and there is no useful next',
|
||||
'action. Do not mark complete after only producing a plan, summary, first pass, or partial',
|
||||
'result. Before calling `complete`, check that every required part of the objective is done,',
|
||||
'completion criteria are satisfied, requested or expected validation passed or has been',
|
||||
'reported as impossible, and no known material task remains. Call UpdateGoal with `blocked`',
|
||||
'only for a genuine impasse: an external condition, required user input, missing credentials',
|
||||
'or permissions, a persistent technical failure, or an impossible, unsafe, or contradictory',
|
||||
'objective. Do not use `blocked` because the work is large, hard, slow, uncertain, partial,',
|
||||
'still needs validation, or needs more goal turns. Do not ask the user for input unless a real',
|
||||
'blocker prevents progress.',
|
||||
'action. Completion audit: before calling `complete`, verify the current state against the',
|
||||
'actual objective and every explicit requirement. Treat weak or indirect evidence as not',
|
||||
'complete. Do not mark complete after only producing a plan, summary, first pass, or partial',
|
||||
'result. Do not mark complete merely because a budget is nearly exhausted or you want to stop.',
|
||||
'Blocked audit: do not call UpdateGoal with `blocked` the first time you hit a blocker. Use',
|
||||
'`blocked` only for a genuine impasse: an external condition, required user input, missing',
|
||||
'credentials or permissions, or a persistent technical failure. For those non-terminal',
|
||||
'blockers, the same blocking condition must repeat for at least 3 consecutive goal turns before',
|
||||
'you call `blocked`, counting the original/user-triggered turn and automatic continuations.',
|
||||
'If a previously blocked goal is resumed, treat the resumed run as a fresh blocked audit.',
|
||||
'Exception: if the objective itself is impossible, unsafe, or contradictory, call UpdateGoal',
|
||||
'with `blocked` in the same turn; do not run more goal turns just to satisfy the audit. Do not',
|
||||
'use `blocked` because the work is large, hard, slow, uncertain, incomplete, still needs',
|
||||
'validation, would benefit from clarification, or needs more goal turns. Once the 3-turn',
|
||||
'threshold is met and you cannot make meaningful progress without user input or an',
|
||||
'external-state change, call UpdateGoal with `blocked`; do not keep reporting the blocker while',
|
||||
'leaving the goal active. Do not ask the user for input unless a real blocker prevents progress.',
|
||||
].join(' ');
|
||||
|
||||
export class TurnFlow {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
Set the status of the current goal. This is how you resume, complete, or block an autonomous goal.
|
||||
|
||||
- `active` — resume a paused or blocked goal when the user explicitly asks you to work on that goal.
|
||||
- `complete` — the objective is satisfied and any stated validation has passed. The goal ends and a completion summary is recorded.
|
||||
- `blocked` — a genuine impasse prevents useful progress: an external condition, required user input, missing credentials or permissions, a persistent technical failure, or an impossible, unsafe, or contradictory objective. The goal stops but can be resumed later. Do not use `blocked` because the work is large, hard, slow, uncertain, partial, still needs validation, or needs more goal turns.
|
||||
- `complete` — the objective is satisfied and any stated validation has passed. The goal ends and a completion summary is recorded. Before using this, verify the current state against the actual objective and every explicit requirement. Treat weak or indirect evidence as not complete. Do not use `complete` merely because a budget is nearly exhausted or you want to stop.
|
||||
- `blocked` — a genuine impasse prevents useful progress: an external condition, required user input, missing credentials or permissions, a persistent technical failure, or an impossible, unsafe, or contradictory objective. For non-terminal blockers, do not use `blocked` the first time you hit the blocker. The same blocking condition must repeat for at least 3 consecutive goal turns before you call `blocked`, counting the original/user-triggered turn and automatic continuations. If a previously blocked goal is resumed, treat the resumed run as a fresh blocked audit. If the objective itself is impossible, unsafe, or contradictory, call `blocked` in the same turn instead of running more goal turns. Do not use `blocked` because the work is large, hard, slow, uncertain, incomplete, still needs validation, would benefit from clarification, or needs more goal turns. Once the 3-turn threshold is met and you cannot make meaningful progress without user input or an external-state change, call `blocked` instead of leaving the goal active.
|
||||
|
||||
Most active goal turns should not call this tool. If you complete one useful slice of work and material work remains, end the turn normally without calling UpdateGoal; the runtime will prompt you to continue in the next goal turn. Call `complete` only when all required work is done, any stated validation has passed, and there is no useful next action. Before calling `complete`, check that every required part of the objective is done, completion criteria are satisfied, requested or expected validation passed or has been reported as impossible, and no known material task remains. Do not call `complete` after only producing a plan, summary, first pass, or partial result. If you call `blocked`, you will be prompted to explain the blocker in your next message. Setting the status is the machine-readable signal; the completion summary or blocker explanation is yours to write in the following message.
|
||||
Most active goal turns should not call this tool. If you complete one useful slice of work and material work remains, end the turn normally without calling UpdateGoal; the runtime will prompt you to continue in the next goal turn. Call `complete` only when all required work is done, any stated validation has passed, and there is no useful next action. Do not call `complete` after only producing a plan, summary, first pass, or partial result. Call `blocked` only after the blocked audit threshold is met. If you call `blocked`, you will be prompted to explain the blocker in your next message. Setting the status is the machine-readable signal; the completion summary or blocker explanation is yours to write in the following message.
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ export const UpdateGoalToolInputSchema = z
|
|||
.object({
|
||||
status: z
|
||||
.enum(['active', 'complete', 'blocked'])
|
||||
.describe('The lifecycle status to set for the current goal.'),
|
||||
.describe(
|
||||
'The lifecycle status to set for the current goal. Use `blocked` for impossible, unsafe, or contradictory objectives, or after the same non-terminal blocking condition repeats for at least 3 consecutive goal turns.',
|
||||
),
|
||||
})
|
||||
.strict();
|
||||
|
||||
|
|
|
|||
|
|
@ -176,15 +176,27 @@ describe('GoalInjector content', () => {
|
|||
expect(text).toContain('Goal mode is iterative');
|
||||
expect(text).toContain('one bounded, useful slice of work');
|
||||
expect(text).toContain('end the turn normally without calling UpdateGoal');
|
||||
expect(text).toContain('Completion audit');
|
||||
expect(text).toContain('actual objective and every explicit requirement');
|
||||
expect(text).toContain('weak or indirect evidence');
|
||||
expect(text).toContain('Do not mark complete after only producing a plan');
|
||||
expect(text).toContain('budget is nearly exhausted');
|
||||
});
|
||||
|
||||
it('reserves blocked for genuine impasses rather than ordinary unfinished work', async () => {
|
||||
const store = makeStore();
|
||||
await store.createGoal({ objective: 'finish the migration' });
|
||||
const text = (await injectOnce(store))!;
|
||||
expect(text).toContain('Blocked audit');
|
||||
expect(text).toContain('do not call UpdateGoal with `blocked` the first time');
|
||||
expect(text).toContain('only for a genuine impasse');
|
||||
expect(text).toContain('missing credentials or permissions');
|
||||
expect(text).toContain('3 consecutive goal turns');
|
||||
expect(text).toContain('fresh blocked audit');
|
||||
expect(text).toContain('Exception: if the objective itself is impossible, unsafe, or contradictory');
|
||||
expect(text).toContain('do not run more goal turns just to satisfy the audit');
|
||||
expect(text).toContain('would benefit from clarification');
|
||||
expect(text).toContain('do not keep reporting the blocker while leaving the goal active');
|
||||
expect(text).toContain('needs more goal turns');
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,12 @@ describe('goal session end-to-end', () => {
|
|||
expect(continuationHistory).toContain('Keep the self-audit brief');
|
||||
expect(continuationHistory).toContain('do not run another goal turn');
|
||||
expect(continuationHistory).toContain('end the turn normally without calling UpdateGoal');
|
||||
expect(continuationHistory).toContain('Completion audit');
|
||||
expect(continuationHistory).toContain('Blocked audit');
|
||||
expect(continuationHistory).toContain('3 consecutive goal turns');
|
||||
expect(continuationHistory).toContain('fresh blocked audit');
|
||||
expect(continuationHistory).toContain('impossible, unsafe, or contradictory');
|
||||
expect(continuationHistory).toContain('do not run more goal turns just to satisfy the audit');
|
||||
expect(continuationHistory).toContain('only for a genuine impasse');
|
||||
|
||||
// Terminal UpdateGoal asks the model for one final user-facing summary.
|
||||
|
|
|
|||
|
|
@ -294,6 +294,10 @@ describe('UpdateGoalTool', () => {
|
|||
const description = new UpdateGoalTool(fakeAgent()).description.toLowerCase();
|
||||
// Reserve blocked for genuine impasses, not ordinary unfinished work.
|
||||
expect(description).toContain('genuine impasse');
|
||||
expect(description).toContain('3 consecutive goal turns');
|
||||
expect(description).toContain('fresh blocked audit');
|
||||
expect(description).toContain('impossible, unsafe, or contradictory');
|
||||
expect(description).toContain('same turn instead of running more goal turns');
|
||||
expect(description).toContain('hard, slow');
|
||||
expect(description).toContain('needs more goal turns');
|
||||
// UpdateGoal also injects the completion/blocked outcome prompt, so it does
|
||||
|
|
@ -301,11 +305,22 @@ describe('UpdateGoalTool', () => {
|
|||
expect(description).not.toContain('only records the status');
|
||||
});
|
||||
|
||||
it('exposes the blocked-audit rule in the status parameter schema', () => {
|
||||
const statusDescription =
|
||||
((new UpdateGoalTool(fakeAgent()).parameters as {
|
||||
properties: Record<string, { description?: string }>;
|
||||
}).properties['status']?.description) ?? '';
|
||||
expect(statusDescription).toContain('3 consecutive goal turns');
|
||||
expect(statusDescription).toContain('impossible, unsafe, or contradictory objectives');
|
||||
});
|
||||
|
||||
it('discourages calling UpdateGoal after a non-terminal work slice', () => {
|
||||
const description = new UpdateGoalTool(fakeAgent()).description;
|
||||
expect(description).toContain('Most active goal turns should not call this tool');
|
||||
expect(description).toContain('end the turn normally without calling UpdateGoal');
|
||||
expect(description).toContain('every required part of the objective is done');
|
||||
expect(description).toContain('actual objective and every explicit requirement');
|
||||
expect(description).toContain('weak or indirect evidence');
|
||||
expect(description).toContain('budget is nearly exhausted');
|
||||
});
|
||||
|
||||
// Keep a capturing context here to prove terminal paths no longer append a
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue