feat: add filter hooks so taxonomy-owning plugins can enrich AI tool descriptions and refuse AI-supplied values#2154
Conversation
…descriptions and refuse AI-supplied values
TaxonomyHandler now fires two filters that let the plugin that owns a
taxonomy attach domain semantics without polluting Data Machine core:
- 'datamachine_taxonomy_tool_parameter' fires in getTaxonomyToolParameters()
after the auto-generated description is built. Consumers can replace the
description, add an enum constraint, mark the field required, change the
type, etc. Default behavior is unchanged when no filter is hooked.
- 'datamachine_taxonomy_assign_value' fires in assignTaxonomy() before
processTerms() runs. Consumers can mutate, sanitize, or refuse the
AI-supplied value. Returning empty (''/null/array()) skips assignment
for that taxonomy without raising an error - useful for taxonomies that
are derived from another data source and the AI must never pick.
Both filters are documented inline with usage examples that reference a
generic 'region' taxonomy, not any vendor-specific taxonomy. DM core
remains oblivious to any specific taxonomy name.
Closes #2152
|
@Chubes ready for review. Diff summary``` What's in here
Both filters documented inline with usage examples referencing a generic Test output
Default behavior unchangedWhen no filter is hooked, both paths produce byte-identical output to pre-#2152. DownstreamThe extrachill-events consumer (extrachill-events#98 — making |
Homeboy Results —
|
Summary
Adds two filter hooks to
TaxonomyHandlerso plugins that own a taxonomy can attach domain semantics — enrich the AI tool description, addenumconstraints, refuse AI-supplied values — without polluting Data Machine core with any vendor-specific taxonomy knowledge.Closes #2152.
What changed
inc/Core/WordPress/TaxonomyHandler.phpNew filter:
datamachine_taxonomy_tool_parameterFires inside
getTaxonomyToolParameters()after the auto-generated description is built, before the param def is added to the returned array. Lets a taxonomy-owning plugin:enumconstraint to lock the AI to a fixed term list.required.type/itemsif needed.Signature:
apply_filters( 'datamachine_taxonomy_tool_parameter', array $param_def, WP_Taxonomy $taxonomy, array $handler_config, ?string $post_type )New filter:
datamachine_taxonomy_assign_valueFires inside
assignTaxonomy()beforeprocessTerms()runs. Lets a taxonomy-owning plugin:''/null/array()—assignTaxonomy()then returns a clean success result withterm_count: 0and no terms are created. No error raised, no junk terms.Signature:
apply_filters( 'datamachine_taxonomy_assign_value', mixed $taxonomy_value, string $taxonomy_name, int $post_id )Both filters are documented in the method docblocks with inline usage examples that reference a generic
regiontaxonomy — not any specific Extra Chill taxonomy.tests/Unit/Core/WordPress/TaxonomyHandlerFiltersTest.phpNew test file with 5 cases covering the contract:
datamachine_taxonomy_tool_parametercan replace description and addenum, and receives full context (taxonomy,handler_config,post_type).assignTaxonomy()creates terms when no filter is hooked.datamachine_taxonomy_assign_valuereturning''refuses creation silently (no term, no error).datamachine_taxonomy_assign_valuecan coerce the value to a different term.The test registers a generic
dm_test_regiontaxonomy inset_up()and tears it down intear_down()— no specific Extra Chill taxonomy name appears.Layer purity check
```
$ grep -E 'location|venue|artist|festival' inc/Core/WordPress/TaxonomyHandler.php
$ echo exit=$?
exit=1
```
Zero matches.
TaxonomyHandlerremains generic.Default behavior unchanged
When no filter is hooked:
getTaxonomyToolParameters()returns the exact same shape as before (verified bytest_default_tool_parameter_is_unchanged_when_no_filter_hooked).assignTaxonomy()creates terms exactly as before (verified bytest_default_assignment_creates_term_when_no_filter_hooked).Test output
homeboy test data-machine— 1325 passed, 3 skipped, 1 failed.The single failure (
ContentActionHandlersTest::test_resolved_pending_action_fires_hook_once) is pre-existing onmainand unrelated to this PR — confirmed by running the suite against the base branch.All 5 new
TaxonomyHandlerFiltersTestcases pass. Verified the tests are meaningful by running them against the unfiltered baseline (where the implementation hooks don't exist yet) — 3 of the 5 tests fail there as expected, proving the filters are doing real work.Out of scope
This PR adds the hooks but does not add any consumers for them. The downstream extrachill-events work (using these hooks so
locationis derived from venue, never AI-decided) is Extra-Chill/extrachill-events#98 and ships in a separate PR.