mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-18 00:56:30 +03:00
test: scenario 19 documentation case when the context launcher is denied (#791)
* Add degraded Setup path: must-read pack when the context launcher is refused When the host denies the impeccable context launcher (issue #789, measured in #744), the Setup fallback now names the degraded path and its unconditional must-read pack: the routed command's reference and craft-floor.md before any UI edit, and document.md before writing DESIGN.md. init.md gains the degraded Step 1 behavior, docs/CLI-CONTRACT.md documents the degraded contract, and scenario 19 gains a denied-launcher documentation case asserting document.md and source reads precede the DESIGN.md write. No version bump, no changelog entry, no generated harness sync. AI was used for assistance. Includes AI_PR_NOTICE.txt per the repository's contribution policy: this change was prepared without maintainer approval on issue #789, so no PR is opened by the agent. Co-authored-by: Matt Van Horn <mvanhorn@users.noreply.github.com> * Drop restated degraded-setup prose; keep the scenario 19 documentation case The launcher-unavailable path already lives on main. This removes the notice file and the restated SKILL, init, and CLI-contract text, and keeps the denied-launcher documentation coverage. The notice must now land before the first tool call after the denial, not only before the eventual write. AI was used for assistance. Co-authored-by: Matt Van Horn <mvanhorn@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor Agent
parent
67d018fe05
commit
7a7579858c
@@ -61,17 +61,25 @@ export function assertNewWorkLifecycle(trace, { target, redesign = false }) {
|
||||
|
||||
export const LAUNCHER_FAILURE_WARNING = /(?:context|launcher|bash)[^.!?\n]{0,160}(?:denied|refused|unavailable|blocked|could(?:n't| not)|cannot|can't|did(?:n't| not)|fail|unable)|(?:denied|refused|unavailable|blocked|could(?:n't| not)|cannot|can't|unable)[^.!?\n]{0,160}(?:context|launcher|bash)/i;
|
||||
|
||||
export function assertPlanningFallbackWarning(responseMessages) {
|
||||
const blocks = responseMessages.flatMap((message) =>
|
||||
function responseBlocks(responseMessages) {
|
||||
return responseMessages.flatMap((message) =>
|
||||
(typeof message.content === 'string' ? [{ type: 'text', text: message.content }] : message.content)
|
||||
.map((block) => ({ ...block, role: message.role })),
|
||||
);
|
||||
}
|
||||
|
||||
function contextLauncherDenialIndex(blocks) {
|
||||
const contextCalls = new Set(blocks.filter((block) => block.role === 'assistant'
|
||||
&& block.type === 'tool-call' && block.toolName === 'bash'
|
||||
&& /impeccable\s+context\b/.test(block.input?.command ?? '')).map((block) => block.toolCallId));
|
||||
const denialIndex = blocks.findIndex((block) => block.role === 'tool'
|
||||
return blocks.findIndex((block) => block.role === 'tool'
|
||||
&& block.type === 'tool-result' && contextCalls.has(block.toolCallId)
|
||||
&& block.output?.type === 'text' && /Bash permission denied by the host/.test(block.output.value));
|
||||
}
|
||||
|
||||
export function assertPlanningFallbackWarning(responseMessages) {
|
||||
const blocks = responseBlocks(responseMessages);
|
||||
const denialIndex = contextLauncherDenialIndex(blocks);
|
||||
assert.ok(denialIndex >= 0, 'must observe the context launcher denial in the response sequence');
|
||||
const warningIndex = blocks.findIndex((block, index) => index > denialIndex
|
||||
&& block.role === 'assistant' && block.type === 'text' && LAUNCHER_FAILURE_WARNING.test(block.text));
|
||||
@@ -81,3 +89,16 @@ export function assertPlanningFallbackWarning(responseMessages) {
|
||||
assert.ok(warningIndex > denialIndex && contextReadIndex > warningIndex,
|
||||
'planning fallback must warn after denial and before reading project context, not only in the final response');
|
||||
}
|
||||
|
||||
export function assertLauncherDenialWarningBeforeNextTool(responseMessages) {
|
||||
const blocks = responseBlocks(responseMessages);
|
||||
const denialIndex = contextLauncherDenialIndex(blocks);
|
||||
assert.ok(denialIndex >= 0, 'must observe the context launcher denial in the response sequence');
|
||||
const warningIndex = blocks.findIndex((block, index) => index > denialIndex
|
||||
&& block.role === 'assistant' && block.type === 'text' && LAUNCHER_FAILURE_WARNING.test(block.text));
|
||||
const nextToolIndex = blocks.findIndex((block, index) => index > denialIndex
|
||||
&& block.role === 'assistant' && block.type === 'tool-call');
|
||||
assert.ok(nextToolIndex >= 0, 'must continue with a tool call after the denied launcher');
|
||||
assert.ok(warningIndex > denialIndex && nextToolIndex > warningIndex,
|
||||
'must disclose the failed context launcher before the first tool call after the denial, not only before the eventual write');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user