Without /D, "$" also matches before a trailing "\n", so "custom_meta_telefon\n",
a color setting "5\n" (stored as sent) or a whole reference followed by "\n"
passed VariableRef. Added /D to every ^...$ pattern that validates client or
admin input:
- VariableRef META_KEY, NUMBER, WHOLE (canonical/typeOf; Placeholders::field
shares META_KEY)
- Cursor::decode, GuideRepository topic names (MCP input and filter keys)
- ExposurePolicy::sanitize ability keys and group ids, LogTab list filters
Not changed: Placeholders::PATTERN (runs on trim()), Warnings hex checks (hints
only), NodeSummary/AttrPathIndex/LogListTable (stored or Divi data, no client
input). Each fixed pattern has a test with a trailing "\n" that is rejected.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
tests/Support/AssertsToolErrors (used by TestCase): assertToolError($result, code)
checks the WP_Error code lit_<code> and the code of the client JSON and returns the
payload; clientError() decodes the payload; errorFields() returns the fields and
asserts they exist. Replaces the private clientError() decoders of
DiviWriteAbilitiesTest/DiviReplaceTextAbilityTest, 216 single-line
assertSame('lit_…', …->get_error_code()) assertions, 24 get_error_data()['fields']
digs and two json_decode(message) reads. ErrorsTest keeps json_decode: it tests
the format itself. Tests 1404 -> 1409 (AssertsToolErrorsTest); no test has fewer
assertions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>