Files
pbakaus_impeccable/tests/skill-behavior/assertions.mjs
T
Paul BakausandGitHub 8426ac2f9a Clarify launcher-refusal fallback and correct behavior tests (#756)
* Clarify permitted work after launcher refusal

Correct behavior-test skill metadata and DeepSeek output limits; document the measured remaining Gemini warning-order failure and hook download trust boundary.

AI assistance: Codex, under pbakaus direction.

* Clarify behavior harness host-modeling scope

AI assistance: Codex, under pbakaus direction.

* Preserve planning-only scope after launcher refusal

Clarify applicable setup steps and cover denied-launcher planning. Retain the observed playbook-read failure under issue #744 rather than weakening its assertion.

AI assistance: Codex, under pbakaus direction.

* Test planning fallback warning order

Require an assistant warning after context launcher denial and before fallback context reads. Cover silent, late, and unrelated warnings with deterministic tests; retain the observed Sonnet omission under #744.

AI assistance: Codex, under pbakaus direction.
2026-09-06 20:34:28 -07:00

25 lines
1.8 KiB
JavaScript

import assert from 'node:assert/strict';
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) =>
(typeof message.content === 'string' ? [{ type: 'text', text: message.content }] : message.content)
.map((block) => ({ ...block, role: message.role })),
);
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'
&& block.type === 'tool-result' && contextCalls.has(block.toolCallId)
&& block.output?.type === 'text' && /Bash permission denied by the host/.test(block.output.value));
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 contextReadIndex = blocks.findIndex((block, index) => index > denialIndex
&& block.role === 'assistant' && block.type === 'tool-call' && block.toolName === 'read'
&& /(?:^|\/)(?:PRODUCT|DESIGN)\.md$/.test(block.input?.path ?? ''));
assert.ok(warningIndex > denialIndex && contextReadIndex > warningIndex,
'planning fallback must warn after denial and before reading project context, not only in the final response');
}