ktg-plugin-marketplace/plugins/config-audit/tests/commands/action-commands-shape.test.mjs
Kjell Tore Guttormsen 347d4a2c4c feat(humanizer): update action command templates [skip-docs]
Wave 5 Step 15. Threads --raw plumbing through all seven action
command templates and adds a shape test covering structural plumbing
plus help.md's plain-language vocabulary.

- commands/fix.md: --raw flag parsed; fix-plan rendering groups by
  userActionLanguage; humanized title/description/recommendation are
  rendered verbatim from the cross-referenced scan envelope.
- commands/rollback.md: terminology pass — "manifest" → "list of
  changes" in user-facing copy; the file name manifest.yaml is kept
  as the machine contract; --raw threaded through.
- commands/plan.md: --raw forwarded to the planner-agent's prompt;
  agent now instructed to group actions by userImpactCategory and
  lead with userActionLanguage; bash block added for flag parsing.
- commands/implement.md: --raw forwarded to the implementer-agent's
  prompt; progress-log lines now reference the humanized titles
  already present in the action plan.
- commands/cleanup.md: --raw accepted as no-op (cleanup is
  file-management only, no findings prose); bash block added.
- commands/help.md: full plain-language pass — "PreToolUse" and
  "frontmatter" jargon removed from user-facing copy; new
  vocabulary table surfaces the humanized userImpactCategory and
  userActionLanguage labels ("Configuration mistake", "Conflict",
  "Wasted tokens", "Missed opportunity", "Dead config" / "Fix this
  now", "Fix soon", "Fix when convenient", "Optional cleanup",
  "FYI"); --raw documented as global pass-through flag.
- commands/interview.md: --raw accepted as no-op; "unused hooks"
  question phrased as "unused automation that runs at specific
  events" in user-facing copy.

tests/commands/action-commands-shape.test.mjs (new, +6 tests, 780 → 786):
  - structural: bash block + Read tool + --raw/$ARGUMENTS plumbing
    across all 7 files
  - help.md vocabulary: ≥3 userImpactCategory labels and ≥3
    userActionLanguage phrases present
  - help.md jargon: no bare "PreToolUse" or "frontmatter" in copy
2026-05-01 19:50:47 +02:00

89 lines
3.9 KiB
JavaScript

/**
* Wave 5 Step 15 — Action-command-template shape tests.
*
* Verifies that the 7 action command templates have the correct structural
* shape after the humanizer integration:
*
* - All 7 files: contain a Bash invocation block, reference the Read tool,
* and contain the `--raw` flag (or the literal `"$ARGUMENTS"` string) so
* `--raw` plumbing is uniform across the toolchain.
*
* - help.md additionally: removes the most obviously technical jargon
* ("PreToolUse" / "frontmatter" mentions in the user-facing prose) and
* introduces a plain-language vocabulary table referencing the
* humanized userImpactCategory and userActionLanguage labels.
*/
import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { readFile } from 'node:fs/promises';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const COMMANDS_DIR = resolve(__dirname, '..', '..', 'commands');
const ACTION_FILES = [
'fix.md',
'rollback.md',
'plan.md',
'implement.md',
'cleanup.md',
'help.md',
'interview.md',
];
const RAW_OR_ARGUMENTS_REGEX = /--raw|"\$ARGUMENTS"/;
const BASH_BLOCK_REGEX = /```bash\b/;
const READ_TOOL_REGEX = /\bRead\s+tool\b|allowed-tools:.*\bRead\b/;
async function readCommand(name) {
return await readFile(resolve(COMMANDS_DIR, name), 'utf-8');
}
test('Action: every file contains a Bash invocation block', async () => {
for (const name of ACTION_FILES) {
const content = await readCommand(name);
assert.match(content, BASH_BLOCK_REGEX, `${name} missing bash block`);
}
});
test('Action: every file references the Read tool', async () => {
for (const name of ACTION_FILES) {
const content = await readCommand(name);
assert.match(content, READ_TOOL_REGEX, `${name} missing Read tool reference`);
}
});
test('Action: every file contains --raw or "$ARGUMENTS" (pass-through plumbing)', async () => {
for (const name of ACTION_FILES) {
const content = await readCommand(name);
assert.match(content, RAW_OR_ARGUMENTS_REGEX, `${name} missing --raw / $ARGUMENTS plumbing`);
}
});
test('help.md: introduces plain-language vocabulary referencing humanized categories', async () => {
const content = await readCommand('help.md');
// At least three of the userImpactCategory labels should appear
const labels = ['Configuration mistake', 'Conflict', 'Wasted tokens', 'Missed opportunity', 'Dead config'];
const present = labels.filter(l => content.includes(l));
assert.ok(present.length >= 3, `help.md must surface ≥3 humanized impact labels; found ${present.length}: ${present.join(', ')}`);
// At least three of the userActionLanguage phrases should appear
const actions = ['Fix this now', 'Fix soon', 'Fix when convenient', 'Optional cleanup', 'FYI'];
const presentActions = actions.filter(a => content.includes(a));
assert.ok(presentActions.length >= 3, `help.md must surface ≥3 humanized action phrases; found ${presentActions.length}: ${presentActions.join(', ')}`);
});
test('help.md: no bare "PreToolUse" jargon in user-facing copy', async () => {
const content = await readCommand('help.md');
// Allow the word in code/quoted contexts but the body table descriptions should not lean on it.
// Heuristic: no occurrence of "PreToolUse" outside of code spans / quoted blocks.
// Simple check: no "PreToolUse" anywhere except in any backtick span — since this file is doc-only,
// require zero occurrences.
assert.doesNotMatch(content, /\bPreToolUse\b/, 'help.md user copy must not lean on "PreToolUse" jargon — use plain language');
});
test('help.md: no bare "frontmatter" jargon in user-facing copy', async () => {
const content = await readCommand('help.md');
assert.doesNotMatch(content, /\bfrontmatter\b/, 'help.md user copy must not lean on "frontmatter" jargon — use plain language ("metadata block at the top of each file")');
});