Contradiction between AI skills and resource standards

Sim

Well-known member
Licensed customer
There seems to be a contradiction between the AI skills and the resource standards - or at least some ambiguity.


20. Where a specific code event exists, a listener should be created to utilise it rather than a full class extension.​

... compared to:


Skill installed to .agents/skills/xf-addon-dev/references/addon-checklist.md:30 from running xf-dev:install-ai-agents

Prefer class extensions over code event listeners when modifying class behavior. Code event listeners are better for cross-cutting concerns at specific execution points.​

The wording is sufficiently ambiguous that my agent picked it up and got quite confused about which is actually preferred.

I think some additional clarity in both sources might help remove some of the uncertainty here.
 
While this may end up changing in the skill documentation to an extent, I'm seeing it more as a documentation/ethos/best practices thing than a bug itself.

I'll come back to this. I'm of the opinion that the skill is more broadly correct. It may need some clarification but I think the main thing that's perhaps overstated is probably the resource standards. Though I should point out that language is important here. If the resource standards say you "should" do something, that's not the same as meaning you "must" do something.

I don't think I've personally used a code event listener over a class extension for a long time to be honest. Usually because, e.g. things like modifying entities, updating the entity structure, pre/post save events usually go hand in hand and doing a listener for each is less efficient and less developer friendly than just extending the class and overriding everything in there.

Part of it too was born out of the fact that with class extensions it can be easier to completely **** it up and break other add-ons in the chain, e.g. forgetting to call parent::method() but that's much less of a concern, in theory, with AI driven development as they wouldn't usually make mistakes with that.
 
I don't think I've personally used a code event listener over a class extension for a long time to be honest.

For the most part, I've found the same - code event listeners are generally few and far between.

However, there are some clear exceptions - for example, adding mail providers where listening to the mailer_transport_setup event is clearly the intended extention point.

There are a few other similar cases where the event listener is far cleaner and less error-prone than extending an entire class would be.

Personally, I'm not sure there even needs to be a distinction made? I seem to recall at one point there was talk about completely deprecating code event listeners in favour of class extensions - but that stance seems to have been softened somewhat, unless I've misinterpreted comments made in the past? I feel there is a valid use for both, and we don't necessarily need to preference one over the other?

Anyway - if it ends up just being a refinement of language rather than a change in policy - I'm happy with that. I just need to be able to calm my agent down because it got all bothered when I asked it to read the resource standards and see how well my existing xenforo-addon-audit skill fit and it noted the discrepancy. I don't need it constantly nagging me about code choices that are actually considered acceptable!
 
20. Where a specific code event exists, a listener should be created to utilise it rather than a full class extension.
Point 20 has been updated to:

20. Where a documented code event provides the complete behavior needed at a single execution point, a listener should generally be preferred. This is not an absolute requirement: use a class extension when the behavior requires coordinated changes to a class, entity structure, validation, save lifecycle, or return flow.
 
  • Like
Reactions: Sim
We've also clarified a few points in the AI skill stubs themselves:

Diff:
Index: src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/references/addon-checklist.md.stub
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/references/addon-checklist.md.stub b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/references/addon-checklist.md.stub
--- a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/references/addon-checklist.md.stub    (revision 704580f74a79782ae09034bc184da5a87fcb2574)
+++ b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/references/addon-checklist.md.stub    (revision 4fc88d8f0f0ad7e2750890a8f43a703303341a5d)
@@ -13,6 +13,9 @@
 3. Use the add-on's existing abstractions and naming. Do not introduce a parallel architecture for one feature.
 4. Check permissions and ownership at the controller/service boundary for user-triggered operations.
 5. Account for enable, disable, uninstall, and upgrade behavior where the feature stores data or registers handlers.
+6. Prefer Finder/entity APIs for database work. If a direct query is justified, use the default XF database adapter with prepared statements, constrain its conditions, and check that loops or relations do not introduce unexpected query growth.
+7. Filter user input through the XF input filterer and preserve automatic output escaping. Check HTML, JavaScript, template modifications, and any explicitly unescaped output for XSS risks.
+8. Use the framework's HTTP client, filesystem, mail, image, and other relevant services rather than manual replacements. Escape arguments passed to `exec`-style functions.
 
 ## Setup.php Upgrade Steps
 
@@ -32,6 +35,21 @@
 4. Treat execution order as a compatibility tool, not a substitute for composable behavior.
 5. Add entity relations through an entity class extension. Pair added columns with `Setup.php` schema changes and the supported entity-structure extension mechanism.
 
+When deciding between a class extension and a code-event listener, use the complete behavior as the test: a listener is preferable for a self-contained action at a documented event point; a class extension is preferable when related behavior spans methods or needs entity structure, validation, save lifecycle, or return/control-flow changes. The existence of an event alone does not make a listener mandatory.
+
+## Public Resource Manager Release
+
+When the add-on will be distributed through the public Resource Manager, review the current [resource standards](https://xenforo.com/community/help/resource-standards/) and [resource guidelines](https://xenforo.com/community/help/resource-guidelines/) in addition to this checklist. The published wording distinguishes hard requirements such as "must" from defaults or recommendations such as "should" and "where possible": follow the recommendation by default, and document a concrete framework or design reason when departing from it.
+
+At minimum, verify the following release-specific concerns:
+
+1. The add-on is installable, free of obvious errors, and not encrypted, encoded, or otherwise obfuscated except for a permitted time-limited demo or trial.
+2. New tables and core-table columns use the required add-on prefixes, nullable/defaulted columns, and uninstall cleanup. Do not change core column definitions without a strong reason.
+3. Code events, handlers, data, unique keys, and other registrations are associated with this add-on and use add-on-identifying names. Use the documented handler system where one exists.
+4. Template changes use template modifications rather than rendered-template manipulation, and modifications replace no more of the target than necessary.
+5. Third-party libraries are appropriately licensed. Any license callback, installation dependency, or lifecycle call to an external server is disclosed as required. Uninstallation cannot be blocked by an external server or failed request, and installation/uninstallation does not download executable code.
+6. Release notes identify issues resolved by each Resource Manager update.
+
 ## Registered Data
 
 Content-type fields, permissions, widget definitions, and several other development-output types may not have a make command in the installed version. Check `xf list xf-make`, then follow the UI-first fallback in `xf-shared-policy/references/development-output.md`.
Index: src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub
--- a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub    (revision 704580f74a79782ae09034bc184da5a87fcb2574)
+++ b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub    (revision 4fc88d8f0f0ad7e2750890a8f43a703303341a5d)
@@ -16,12 +16,29 @@
 
 ## Extension Choices
 
-- Use class extensions when adapting an extensible class's behavior.
-- Use code events for the documented event surface and cross-cutting hooks.
-- Add entity columns or tables in `Setup.php`; add entity structure definitions through the supported extension/event mechanism.
+Choose an extension mechanism based on the behavior that must change, not merely on whether a code event exists.
+
+- Use a code-event listener when a documented event provides the complete hook needed for a focused action at one execution point, especially for cross-cutting behavior that does not need to change the owning class's implementation.
+- Use a class extension when behavior belongs to one class and requires coordinated changes across methods, entity structure or relations, validation, the save lifecycle, or return/control flow. Extend the generated `XFCP_<ClassName>` proxy and compose with `parent` as required by the method contract.
+- Use a framework handler system when it is the documented extension contract for the feature, such as spam checking. Do not extend several unrelated classes to simulate a handler.
+- If either a listener or a class extension can express the complete behavior, prefer the least intrusive mechanism that keeps related logic cohesive. Do not split one entity change across several listeners merely because pre-save, post-save, or structure events exist.
+- The public Resource Manager standard that a listener "should" be used where a specific event exists is a default preference when that event is sufficient, not an unconditional requirement. A class extension is appropriate when it is needed for cohesive class-specific behavior; record a non-obvious departure from the preference in the implementation or review notes.
+- Add entity columns or tables in `Setup.php`; add entity structure definitions through the supported entity extension or event mechanism, using the same extension choice for related entity behavior where practical.
 - Prefer services for multi-step writes and repositories/finders for reusable queries.
 - Create factories with native class strings, never legacy short names.
 
+## Framework and Resource Standards
+
+Use XenForo's framework facilities and the current public resource standards when they apply:
+
+- Read and write through Finder/entity APIs where possible. If a direct query is justified, use the default XF database adapter and prepared statements, constrain reads and writes, and check for accidental N+1 query growth.
+- Filter request input through XenForo's input filterer and preserve the framework's escaping. Do not introduce XSS through templates, HTML, JavaScript, or deliberately unescaped output.
+- Use template modifications for changes to existing templates, keep modifications narrow, and use a callback or regular expression when a simple replacement would consume too much of the template.
+- Use the XF HTTP client, filesystem, mail, image, and other framework services rather than reimplementing them. Escape arguments passed to process or exec-style functions.
+- Keep third-party libraries appropriately licensed. Do not obscure released code except for an explicitly permitted, time-limited demo or trial.
+- Public resources must not register listeners or add data unrelated to their add-on. Prefix add-on-owned tables, core columns, template modifications, phrases, and other unique keys according to the published standards.
+- Do not download executable code during installation or uninstallation. Uninstallation must remain possible if an external request fails, and installation or lifecycle calls to external services must be disclosed as required by the resource guidelines.
+
 ## Installation and Upgrades
 
 - Keep fresh-install schema in `installStep*()` or reusable schema methods and changes for installed sites in `upgrade<versionId>Step<n>()`.
Index: src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-template-phrase/SKILL.md.stub
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-template-phrase/SKILL.md.stub b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-template-phrase/SKILL.md.stub
--- a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-template-phrase/SKILL.md.stub    (revision 704580f74a79782ae09034bc184da5a87fcb2574)
+++ b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-template-phrase/SKILL.md.stub    (revision 4fc88d8f0f0ad7e2750890a8f43a703303341a5d)
@@ -17,7 +17,8 @@
 2. Reuse the established structural component, form row, macro, CSS class, responsive utility, and JavaScript behavior before adding markup or LESS.
 3. Use `xf-make:template` and `xf-make:phrase` for new artifacts.
 4. Keep authorization, queries, and domain decisions out of templates. Prepare view data in PHP.
-5. Verify the rendered result at narrow and wide widths, including empty, error, disabled, and long-content states that the change affects.
+5. Use template modifications to inject changes into existing templates rather than manipulating rendered output in PHP. Keep modifications narrow and use a callback or regular expression when a simple replacement would replace too much.
+6. Verify the rendered result at narrow and wide widths, including empty, error, disabled, and long-content states that the change affects.
 
 Read [template-language-semantics.md](references/template-language-semantics.md) before writing expressions or macros. Read [ui-patterns.md](references/ui-patterns.md) before creating or restyling a form, list, menu, overlay, or content block.
 
Call me a rebel but class extension is better than listener in every case, because you can then add your own class docblock and use Vendor\Prefix\XF\Entity\User as ExtendedUserEntity; to get type hints for your custom columns.

Come At Me Bring It GIF by Game of Thrones
 
Call me a rebel but class extension is better than listener in every case, because you can then add your own class docblock and use Vendor\Prefix\XF\Entity\User as ExtendedUserEntity; to get type hints for your custom columns.

Come At Me Bring It GIF by Game of Thrones

... but at the cost of having to consider the fact that your addon may not be the only addon extending the same class and it's pretty easy to break the functionality of other addons if you're not careful.
 
... but at the cost of having to consider the fact that your addon may not be the only addon extending the same class and it's pretty easy to break the functionality of other addons if you're not careful.
I mean sure, but I don't think Monsieur Claude would make that mistake, and the risk is minimal if you're just extending the structure :P
 
One more point on the agent skills - I've had to clearly instruct Claude to ignore the xf-core-dev skill because it kept complaining that the skill referenced tools that did not exist in our XenForo dev install. I pointed out that this was clearly intended for the XenForo core development team and not for us addon developers.

I wonder if it would be better to avoid installing this skill from the default xf-dev:install-ai-agents command for us non-staff folks?
 
One more point on the agent skills - I've had to clearly instruct Claude to ignore the xf-core-dev skill because it kept complaining that the skill referenced tools that did not exist in our XenForo dev install. I pointed out that this was clearly intended for the XenForo core development team and not for us addon developers.

I wonder if it would be better to avoid installing this skill from the default xf-dev:install-ai-agents command for us non-staff folks?
Mind trying the original patch and the following one for a bit? Just apply the patches and re-install the skills and let me know if the same confusion still happens.

Diff:
Subject: [PATCH] fix(ai-skills): make separation between core-dev and addon-dev skills clearer
---
Index: src/XF/Cli/Command/Development/stubs/ai-agents/ROOT.md.stub
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/XF/Cli/Command/Development/stubs/ai-agents/ROOT.md.stub b/src/XF/Cli/Command/Development/stubs/ai-agents/ROOT.md.stub
--- a/src/XF/Cli/Command/Development/stubs/ai-agents/ROOT.md.stub    (revision 4fc88d8f0f0ad7e2750890a8f43a703303341a5d)
+++ b/src/XF/Cli/Command/Development/stubs/ai-agents/ROOT.md.stub    (date 1789737400724)
@@ -55,15 +55,19 @@
 
 Load `xf-shared-policy` with every XenForo task, then only the focused skills needed:
 
+Do not load every installed skill. Determine the ownership of the files being changed before selecting a skill. The presence of `src/XF`, a full XenForo checkout, or a `xenforo-ltd/xenforo` Git remote does not by itself make a task core work; third-party add-ons are commonly developed inside a full core checkout.
+
 | Skill | Use when |
 |---|---|
 | `xf-shared-policy` | Any XenForo code or data change |
 | `xf-environment` | Running commands, accessing MySQL, diagnosing containers, or using worktrees |
-| `xf-core-dev` | Changing core framework, first-party XF data, upgrades, or core-only tests/CI |
-| `xf-addon-dev` | Changing a third-party add-on, Setup.php, or extension behavior |
+| `xf-core-dev` | Changing core framework, first-party XF data, upgrades, or core-only tests/CI. Do not load for third-party add-on work. |
+| `xf-addon-dev` | Changing a third-party add-on, Setup.php, or extension behavior. Do not load for core-only work. |
 | `xf-scaffold-make` | Creating code/data artifacts or checking make-command coverage |
 | `xf-template-phrase` | Templates, phrases, template modifications, LESS, forms, or UI work |
 
+For a third-party add-on task, normally load `xf-shared-policy`, `xf-environment`, and `xf-addon-dev`, adding only the focused UI or scaffolding skill when needed. Do not load `xf-core-dev`, `core-map.md`, or core-only testing/tooling guidance unless the requested change also modifies XenForo core or first-party core data. For a core task, load `xf-core-dev` and do not treat third-party add-on guidance as the authority for core implementation.
+
 Read linked references only when the skill routes the current task to them.
 
 ## Review Quality
Index: src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-core-dev/SKILL.md.stub
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-core-dev/SKILL.md.stub b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-core-dev/SKILL.md.stub
--- a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-core-dev/SKILL.md.stub    (revision 4fc88d8f0f0ad7e2750890a8f43a703303341a5d)
+++ b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-core-dev/SKILL.md.stub    (date 1789737456190)
@@ -1,10 +1,14 @@
 ---
 name: xf-core-dev
-description: Implement or review XenForo core framework work in src/XF, js/xf, src/addons/XF, installation and upgrade code, or core-only tests and CI.
+description: CORE-ONLY. Implement or review XenForo core framework work in src/XF, js/xf, src/addons/XF, installation and upgrade code, or core-only tests and CI. Do not load for third-party add-on work.
 ---
 
 # XenForo Core Development
 
+This is a core-team skill, not a general add-on development skill. Load it only when the requested change targets XenForo core, first-party XF data, installation/upgrade code, or core-only tests/tooling. Do not load it merely because the add-on is being developed inside a full XenForo checkout or because `src/XF` is present.
+
+If the requested change is limited to `src/addons/<Vendor>/<AddOn>` outside the first-party XF paths, stop reading this skill and use `xf-addon-dev` instead.
+
 Load `xf-shared-policy`. Load `xf-environment` before running commands.
 
 ## Work from the Framework Outward
@@ -20,7 +24,7 @@
 
 ## Core-Only Tooling
 
-The repository's Composer scripts, `development/ci`, PHPStan setup, and PHPUnit suite are core development infrastructure. Do not present them as tools shipped to third-party add-on developers.
+The repository's Composer scripts, `development/ci`, PHPStan setup, and PHPUnit suite are core development infrastructure. Do not present them as tools shipped to third-party add-on developers, and do not require them for an add-on-only task just because this skill is installed.
 
 In a managed environment, run scripts through the wrapper:
 
Index: src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub
--- a/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub    (revision 4fc88d8f0f0ad7e2750890a8f43a703303341a5d)
+++ b/src/XF/Cli/Command/Development/stubs/ai-agents/skills/xf-addon-dev/SKILL.md.stub    (date 1789737456248)
@@ -1,10 +1,14 @@
 ---
 name: xf-addon-dev
-description: Implement or review third-party XenForo add-ons, including Setup.php, class extensions, add-on runtime code, development output, and release lifecycle.
+description: THIRD-PARTY ADD-ON ONLY. Implement or review XenForo add-ons, including Setup.php, class extensions, add-on runtime code, development output, and release lifecycle. Do not use for core-only work.
 ---
 
 # XenForo Add-on Development
 
+This is the default skill for third-party add-on work. It applies even when the add-on is developed inside a complete XenForo core checkout. Do not load `xf-core-dev` or use its core-only Composer, CI, PHPStan, or PHPUnit guidance unless the requested change also targets XenForo core or first-party core data.
+
+If the requested change targets only XenForo core or first-party XF data, stop reading this skill and use `xf-core-dev` instead.
+
 Load `xf-shared-policy`. Load `xf-environment` before running commands. Load `xf-template-phrase` for UI or phrase work and `xf-scaffold-make` for new artifacts.
 
 ## Keep Ownership Clear
 
Small data point from a stock 2.3.13 install (XAMPP, no containers): the stubs included there are older than what Sim is quoting. addon-checklist doesn't have the "prefer class extensions" line yet, and xf-core-dev has no core-only guard.

So anyone running xf-dev:install-ai-agents today still gets the version that caused the confusion in the first place. @Chris D Are the patched stubs planned for 2.3.14, or should we just apply the diffs manually for now?

+1 on xf-core-dev. On a normal install it points to Composer scripts, PHPStan and a CI wrapper that simply don't exist, so the agent either complains about them or starts looking for them. My plan was to use --only-claude and then delete .claude/skills/xf-core-dev, but having a flag to skip it, or not installing it by default outside a core checkout, would be cleaner.

One thing I did like: the installer leaves an existing CLAUDE.md alone unless you pass --force, so your own house rules survive.

Worth keeping in mind though that some of the shipped skills can disagree with your own conventions. Mine don't allow comments at all, while the shipped rules allow them for non-obvious reasons, and the factory examples use the Finder/Repository suffix style. Not a bug obviously, but if you already have your own conventions, you'll want to make it clear to the agent which rules take priority.
 
So anyone running xf-dev:install-ai-agents today still gets the version that caused the confusion in the first place. @Chris D Are the patched stubs planned for 2.3.14, or should we just apply the diffs manually for now?
My patches were created today so, clearly, they'll be in a future release if we deem the issues raised are resolved.

+1 on xf-core-dev. On a normal install it points to Composer scripts, PHPStan and a CI wrapper that simply don't exist, so the agent either complains about them or starts looking for them. My plan was to use --only-claude and then delete .claude/skills/xf-core-dev, but having a flag to skip it, or not installing it by default outside a core checkout, would be cleaner.
Hopefully not required.

Mine don't allow comments at all, while the shipped rules allow them for non-obvious reasons
I mean, the obvious reasons are that code comments can be good and useful, though I appreciate the quality and quantity of comments that agents create does vary wildly.

the factory examples use the Finder/Repository suffix style
Yes, as they should. I appreciate older code bases may not or not want to follow that pattern but it is the convention going forward that we're sticking with and add-on developers should follow suit where practical. The suffix being added made reading the code and finding the right code a much simpler task, especially with class level imports and not having to manually alias classes where they collide.
 
Some more changes:
  • Dropped --with-claude and --only-claude options
  • Added --no-symlinks option
  • Since Claude Code 2.1.277, they now read AGENTS.md so CLAUDE.md is no longer written; we recommend upgrading Claude Code and deleting CLAUDE.md
  • Skills are added to .agents/skills by default and, by default, symlinked into .claude/skills rather than being copied (use --no-symlinks to copy instead of linking)
  • You can now modify AGENTS.md safely outside of the <!-- xf:ai-agents:start --> and <!-- xf:ai-agents:end --> markers
 
Back
Top Bottom