test(prompts): fail when the goal hunter prompt loses its node_id lookup key - #1212
Merged
Merged
Conversation
…kup key #1196 replaced the prompt semantic anchors with the REQUIRED_PROMPT_VARIABLES table, but did not carry over the anchor's `{{item.node_id}}` pin for strategies/goal-hunter.mdx. That variable is how each generated threat-goals/class-goals node finds its own entry in a goal plan that lists every goal. Without it the prompt still loads, renders and expands, and all 58 prompts tests pass, while the hunter is left to guess its goal from the label. The goal-search census still records the node's result as coverage of the goal it was generated for. Add the goal hunter to the table, and say in the table comment why that variable belongs there. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The shipped-schema check captured the file name after {{schema_path}}/
and stopped there, so a reference such as
{{schema_path}}/findings.schema.json/obsolete passed although no such
path is shipped. Require that the name is not followed by a word
character, slash or hyphen; a sentence-final period still ends a name.
All current references still pass (Greptile, on #1196).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ot skipped
The previous commit's lookahead made the name end the path, but a
reference such as {{schema_path}}/subdir/findings.schema.json then
matched nothing and escaped the check. Read dots and slashes between
path segments instead, so any longer path is captured whole and fails
the shipped-file check, while a sentence-final period still ends the
path (Greptile, on #1212).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This was referenced Sep 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
{{item.node_id}}lost its test in test: delete vacuous and prompt-prose tests outside the runtime package #1196 (Greptile, P2). test: delete vacuous and prompt-prose tests outside the runtime package #1196 (071080b) deleted the prompt semantic-anchor tests and moved some of their variable pins intoREQUIRED_PROMPT_VARIABLES. The deleted test "makes goal searches read their records from files and stop at a measurable deadline" pinned{{item.node_id}}instrategies/goal-hunter.mdx, with the comment that it "is what makes it resolvable at all". test: delete vacuous and prompt-prose tests outside the runtime package #1196's body listed that test as "wording" only, and the pin was not moved to the table. Each generatedthreat-goals/class-goalsnode (.ultrafuzz/topology.yml,default.yml,exhaustive.yml) uses it to find "the single element ofclass_goalsorthreat_goalswhosenode_idis{{item.node_id}}" in a goal plan that lists every goal. On origin/main 2cacf4c that line can be removed and all 58 prompts tests still pass. The hunter then has to guess its entry from the goal label. The goal-search census still records that node's result as coverage of the goal it was generated for.Change
packages/prompts/test/prompt-structure.test.ts: add"strategies/goal-hunter.mdx": ["item.node_id"]toREQUIRED_PROMPT_VARIABLES. Add one bullet to the table comment saying why it belongs: the goal-search census records the node's result as coverage of the goal it was generated for, anditem.node_idis what picks that goal out of the plan.extractPromptVariablesalready reports this reference asitem.node_id, sorequirementKeysis unchanged. Test-only (+4/-1).Deliberately not fixed
The same Greptile comment also asked to pin these. I left them out:
render.test.ts:543("renders smoke final review with bounded classification semantics and context") renders the shippedreview/final-report.mdand asserts the sha256 selector ids of the exact 10-path machine selector and the exact 4-path setup selector. I checked by editing the prompt file. Droppingaggregation.jsonfrom the machine selector fails that test (expected '…' to contain 'path entry whose `id` is `3311f635787…'). Deleting the setup selector also fails it (expected 1 to be 2). A table entry would add nothing. test: delete vacuous and prompt-prose tests outside the runtime package #1196 also dropped these two pins on purpose ("its two path-selector pins are not kept").setup/project-discovery.md,setup/base-test-setup.md). It is anancestor_*_authorityselector, so it fits the table's comment, but test: delete vacuous and prompt-prose tests outside the runtime package #1196 dropped this pin on purpose ("the optional setup path-selector pin is not kept"), and running without it is a supported degraded mode, so I left that decision alone. The prompt calls it "Optional native-validation context" and says a bounded topology may omit those handoffs. When they are absent, dedupe does one model-only consolidation pass instead (dedupe-findings.md:56-66).Greptile did not flag the deleted test's other lookup pin,
{{artifact_path:goal-plan}}/goal-plan.json, and it stays unpinned. With all three{{artifact_path:goal-plan}}references ingoal-hunter.mdxrewritten as prose, the prompts suite still passes 58/58, and the topologypackaged-topologies,artifact-handoffsandvalidatetests pass 43/43. A table entry would catch only the loss of all three, which takes a deliberate restructure, while{{item.node_id}}appears once and a one-line rewording drops it. If wanted,"strategies/goal-hunter.mdx": ["artifact_path:goal-plan", "item.node_id"]passes with the shipped prompt and fails (strategies/goal-hunter.mdx: {{artifact_path:goal-plan}}: expected 0 to be greater than 0) when those references are gone.No overlap with in-flight work: none of x01-x05, #1202, #1197, #1201, #1198, #1183 or #1162 touches
prompt-structure.test.tsorgoal-hunter.mdx. #1162 touches onlypackages/prompts/test/agent-preamble.test.tsin that directory.Verification
prompt-structure.test.ts› "keeps the template variables that gates, budgets and sealed authorities depend on". This PR closes a test gap, so the discriminating run changes the prompt, not the code. Step 1 ofgoal-hunter.mdxwas rewritten to "…whosenode_idmatches this node.", which removes{{item.node_id}}:prompt-structure.test.tspasses 4/4 and the whole prompts suite passes 58/58.AssertionError: strategies/goal-hunter.mdx: {{item.node_id}}: expected 0 to be greater than 0.prompt-structure.test.tspasses 4/4 and the whole prompts suite passes 58/58.packages/promptsitself built. Itstestscript builds only its dependencies, and withoutpackages/prompts/disttwo packaging tests fail with ENOENT (render.test.ts"renders output-contract guidance from the packaged layout with no repository above it" andscaffold-catalog.test.ts"packs the canonical prompt tree and scaffolds every prompt from the extracted package"). This PR does not touch either test.npx prettier --checkandnpx eslinton the changed file,CI=1 ESLINT_PLUGIN_DIFF_COMMIT=origin/main pnpm -w lint:strict:ci,pnpm -w lint,pnpm --filter @ultrafuzz/prompts typecheckandpnpm -w knipall pass. The package typecheck does not cover tests, so I also rantsc --noEmitover promptssrcandtestwith the base config. It passes.Risk / compatibility
VALIDATOR_BUILD_IDENTITYis unaffected.{{item.node_id}}in the goal hunter now has to remove the table entry too. That is intended.Changelog entry
Test-only; no product behaviour change. The prompt structure test now requires
strategies/goal-hunter.mdxto keep{{item.node_id}}, which each generated threat or class goal node uses to find its own entry in the goal plan. Since #1196, no test caught its removal.Also in this PR
prompt-structure.test.tscaptured the name after{{schema_path}}/and stopped at a slash. So{{schema_path}}/findings.schema.json/obsoletepassed asfindings.schema.json. A first attempt required the name to end the path, but then{{schema_path}}/subdir/findings.schema.jsonmatched nothing and escaped the check. The regex now reads dots and slashes between path segments: any longer path is captured whole and fails the shipped-file check, while a sentence-final period still ends the path. All current references pass (4/4 inprompt-structure.test.ts).🤖 Generated with Claude Code
The PR appears safe to merge.
Summary
The PR pins the goal hunter’s
item.node_idvariable in the prompt-structure test and updates schema-reference matching to validate the whole path, including directory segments.Reviews (3) · Last reviewed commit: "test(prompts): a schema reference with a..."