feat(humanizer): update agent system prompts [skip-docs]
Wave 5 Step 16 — final wave step. Threads humanizer-aware rendering
rules through the three agent prompts that produce user-facing output,
and adds a shape test that locks the structure.
- agents/analyzer-agent.md: documents the humanizer envelope shape
(userImpactCategory, userActionLanguage, relevanceContext) in the
Input section; new "Humanizer-aware rendering rules" subsection
instructs the agent to: render humanized title/description/
recommendation verbatim, group findings by userImpactCategory, lead
each line with userActionLanguage, surface relevanceContext when
not affects-everyone, and skip jargon-translation subroutines.
--raw fallback documented (v5.0.0 verbatim severity prefiks).
- agents/planner-agent.md: documents the same vocabulary; instructs
the planner to consume humanized fields from the analysis report,
preserve titles verbatim, and order actions by both dependencies
AND userActionLanguage urgency. Translation duties explicitly
removed from the plan.
- agents/feature-gap-agent.md: replaces the inline t1/t2/t3/t4
tier-to-prose section ladder with userActionLanguage-driven
groupings ("Fix soon" → High Impact, "Fix when convenient" →
Worth Considering, "Optional cleanup"/"FYI" → Explore When Ready);
instructs skipping findings whose relevanceContext is
test-fixture-no-impact; --raw fallback documented.
tests/agents/agent-prompt-shape.test.mjs (new, +6 tests, 786 → 792):
- structural: humanized field reference + frontmatter preserved
- per-agent anchors: analyzer groups by userImpactCategory; planner
orders by userActionLanguage; feature-gap references
test-fixture-no-impact
- global: no "explain what {jargon} means" / "translate jargon" /
"jargon-translation duty" prose anywhere
Self-audit: Grade A unchanged (config 97/100, plugin 100/100).
This commit is contained in:
parent
347d4a2c4c
commit
ec4ac3e6d1
4 changed files with 136 additions and 27 deletions
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* Wave 5 Step 16 — Agent system-prompt shape tests.
|
||||
*
|
||||
* Verifies that the 3 agent prompt files have the correct structural shape
|
||||
* after the humanizer integration:
|
||||
*
|
||||
* - Each file references at least one of the humanized field names by
|
||||
* name: `userImpactCategory`, `userActionLanguage`, `relevanceContext`.
|
||||
*
|
||||
* - Each file does NOT contain a "explain what X means" subroutine —
|
||||
* those translation duties are owned by the humanizer now.
|
||||
*
|
||||
* - Each file preserves its required frontmatter (name, description,
|
||||
* model, color, tools).
|
||||
*/
|
||||
|
||||
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 AGENTS_DIR = resolve(__dirname, '..', '..', 'agents');
|
||||
|
||||
const AGENT_FILES = [
|
||||
'analyzer-agent.md',
|
||||
'planner-agent.md',
|
||||
'feature-gap-agent.md',
|
||||
];
|
||||
|
||||
const HUMANIZED_FIELD_REGEX = /userImpactCategory|userActionLanguage|relevanceContext/;
|
||||
const JARGON_TRANSLATION_INSTRUCTION_REGEX = /explain\s+what\s+\{[^}]+\}\s+means|translate\s+jargon|jargon[- ]translation\s+duty/i;
|
||||
const FRONTMATTER_REGEX = /^---\s*\nname:\s+\S+/m;
|
||||
|
||||
async function readAgent(name) {
|
||||
return await readFile(resolve(AGENTS_DIR, name), 'utf-8');
|
||||
}
|
||||
|
||||
test('Agent prompts: every file references at least one humanized field', async () => {
|
||||
for (const name of AGENT_FILES) {
|
||||
const content = await readAgent(name);
|
||||
assert.match(
|
||||
content,
|
||||
HUMANIZED_FIELD_REGEX,
|
||||
`${name} must reference userImpactCategory, userActionLanguage, or relevanceContext`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('Agent prompts: no jargon-translation subroutines', async () => {
|
||||
for (const name of AGENT_FILES) {
|
||||
const content = await readAgent(name);
|
||||
assert.doesNotMatch(
|
||||
content,
|
||||
JARGON_TRANSLATION_INSTRUCTION_REGEX,
|
||||
`${name} must not contain "explain what {jargon} means" / "translate jargon" instructions — humanizer owns translation`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('Agent prompts: frontmatter preserved (name field present)', async () => {
|
||||
for (const name of AGENT_FILES) {
|
||||
const content = await readAgent(name);
|
||||
assert.match(content, FRONTMATTER_REGEX, `${name} missing required frontmatter`);
|
||||
}
|
||||
});
|
||||
|
||||
test('analyzer-agent.md: instructs grouping by userImpactCategory', async () => {
|
||||
const content = await readAgent('analyzer-agent.md');
|
||||
assert.match(content, /group.*by\s+`?userImpactCategory`?/i, 'analyzer-agent must group findings by userImpactCategory');
|
||||
});
|
||||
|
||||
test('planner-agent.md: instructs ordering by userActionLanguage', async () => {
|
||||
const content = await readAgent('planner-agent.md');
|
||||
assert.match(content, /order.*by\s+(dependencies\s+and\s+)?`?userActionLanguage`?|userActionLanguage\s+urgency/i, 'planner-agent must order actions by userActionLanguage');
|
||||
});
|
||||
|
||||
test('feature-gap-agent.md: skips test-fixture-no-impact findings', async () => {
|
||||
const content = await readAgent('feature-gap-agent.md');
|
||||
assert.match(content, /test-fixture-no-impact/, 'feature-gap-agent must reference the test-fixture-no-impact relevanceContext');
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue