Files
pbakaus_impeccable/tests/skill-behavior-harness.test.mjs
T
044a04fd0d docs: add workflow guide for command entry points (#737)
* docs: add workflow guide for command entry points

* Refine workflow guidance into advice-only routing

Reuse the existing routing reference and docs map instead of shipping a parallel workflow catalog. Add reference-backed command comparisons, advice-only tests, and explicit-command precedence coverage.

AI-assisted maintainer revision prepared with Codex.

* Include routing guidance in behavior-test triggers

AI-assisted maintainer revision prepared with Codex.

* Constrain routing behavior tests to fixture-safe tools

Keep the real context loader but reject arbitrary host shell searches in the new advice scenarios. Preserve observable project writes and protect the staged skill; cover the restriction with offline regression tests.

AI-assisted maintainer revision prepared with Codex.

* Require actual reference reads in restricted routing tests

Do not count rejected shell reads as reference loading. Record the nine measured advice cases; explicit-command measurements remain pending the stricter retest.

AI-assisted maintainer revision prepared with Codex.

* Record measured workflow-routing baseline

All twelve focused cases pass across Claude Sonnet 5, GPT-5.6 Terra, and Gemini 3.7 Flash, including the stricter explicit-command retest.

AI-assisted verification prepared with Codex.

* Trim workflow routing guidance

Reduce added skill prose from 286 to 59 words while retaining the routing regression assertions. Record the missing-context reference-read flake and passing repeat.

AI assistance: prepared and verified with Codex under maintainer direction.

---------

Co-authored-by: Paul Bakaus <paul.bakaus@gmail.com>
2026-09-05 15:01:58 -07:00

42 lines
2.0 KiB
JavaScript

import { it } from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
import { prepareWorkspace, cleanupWorkspace, makeTools } from './skill-behavior/harness.mjs';
it('context-only routing tools reject shell searches and compound commands before execution', async () => {
const workspace = prepareWorkspace({ files: { 'index.html': 'before' } });
try {
const { tools, trace } = makeTools(workspace, {}, {}, { contextOnlyBash: true });
for (const command of [
'find / -name routing.md',
'.claude/skills/impeccable/scripts/impeccable context; echo bad > index.html',
'echo bad > index.html',
]) {
assert.match(await tools.bash.execute({ command }), /^Error:/);
}
assert.equal(fs.readFileSync(path.join(workspace, 'index.html'), 'utf8'), 'before');
assert.equal(trace.bashCommands.length, 3, 'rejected attempts remain observable');
assert.ok(trace.toolCalls.every((call) => call.mutatedPaths.length === 0));
} finally {
cleanupWorkspace(workspace);
}
});
it('context-only routing tools keep project writes observable but protect the staged skill', async () => {
const workspace = prepareWorkspace({ files: { 'index.html': 'before' } });
try {
const { tools, trace } = makeTools(workspace, {}, {}, { contextOnlyBash: true });
const skillPath = '.claude/skills/impeccable/reference/routing.md';
const before = await tools.read.execute({ path: skillPath });
assert.match(await tools.write.execute({ path: skillPath, contents: 'bad' }), /^Error:/);
assert.equal(await tools.read.execute({ path: skillPath }), before);
await tools.write.execute({ path: 'index.html', contents: 'after' });
assert.equal(fs.readFileSync(path.join(workspace, 'index.html'), 'utf8'), 'after');
assert.deepEqual(trace.writePaths, [skillPath, 'index.html']);
assert.deepEqual(trace.toolCalls.flatMap((call) => call.mutatedPaths), ['index.html']);
} finally {
cleanupWorkspace(workspace);
}
});