User tests: Successful: Unsuccessful:
Pull Request resolves # .
This is the result of Google Summer of Code 2026 for Joomla, mentored by @ditsuke and @Dileepadari. It was developed and reviewed in https://github.com/joomla-projects/gsoc26_automated_workflow and is submitted here as one branch.
Workflow transitions currently have to be run by a person. This adds rules that run them automatically.
The rule. Any transition can carry an automation rule: fire after a delay (minutes, hours, days, months) or on a cron schedule. A new scheduler task, workflow.automation, picks up due items each run and executes their transitions. Every rule runs as a chosen user, so permissions are checked exactly as they would be for a person clicking the button. A super user may choose any run-as user; anyone else may only keep the user the rule already has or pick themselves.
Which items, and when. A filter decides which items a rule applies to, and a condition decides whether the moment is right. Eight built-in checks (category, tag, author group, hits, day of week, date, days in stage, days since modified) with thirteen operators. The builder defaults to a simple mode where checks are joined by AND; OR, Not and nested expressions sit behind an Expert Mode option in the plugin. Two new events, onWorkflowConditionFields and onWorkflowResolveFields, let any extension add its own checks, so the list is not limited to what core knows about.
Visibility. An Upcoming Transitions tab per workflow and a site-wide list with workflow and stage filters, a badge in the articles list and a card in the article edit sidebar, an automation log per workflow and site-wide with the reason for every failure, and automated transitions marked in the workflow graph. Failures record a reason, take the item out of the queue until an administrator clears it, and are reported through the existing task notification plugin.
Schema. Three new tables: #__workflow_automation_rules, #__workflow_item_state and #__workflow_automation_log, with MySQL and PostgreSQL install and update SQL. Each scheduler run reconciles #__workflow_item_state against #__workflow_associations, so items created while workflows were off, moved by a batch stage change or imported directly are picked up rather than silently ignored.
Known gaps, raised here rather than left to be found:
plugins/workflow/remotecheck is an example plugin that asks an external service a yes/no question, written to prove the extension points work. If an example plugin does not belong in core, say so and I will drop those five files.npm ci && npm run build so the new component assets are built.php cli/joomla.php scheduler:run does the same.Every workflow transition has to be run by a person from the articles list or the article itself. There is no way to say "move this to Review three days after it enters Copywriting", no record of when an item entered its stage, and nothing showing what is due to happen next.
Transitions run on their own, on a delay or a schedule, restricted to the items a rule selects, executed as a named user with that user's permissions. The administrator shows what is coming, what has already run and why anything failed.
Please select:
Documentation link for guide.joomla.org:
No documentation changes for guide.joomla.org needed
Pull Request link for manual.joomla.org:
No documentation changes for manual.joomla.org needed
| Status | New | ⇒ | Pending |
| Category | ⇒ | Administration com_admin SQL Postgresql com_content com_workflow |
| Title |
|
||||||
This is a new feature so should be made against the 6.3-dev branch not the 6.2 branch and the sql files need to be renamed accordingly
| Labels |
Added:
Feature
PR-6.2-dev
|
||
Thanks for the thorough review @brianteeman. All the suggestions are in.
you still need to move this to the 6.3dev branch and rename the sql files accordingly. (does it even need two files or can they be combined into a single file now)
| Labels |
Added:
PR-6.3-dev
|
||
| Labels |
Removed:
PR-6.2-dev
|
||
| Title |
|
||||||
A walkthrough for anyone testing this
This is what it looks like and the fastest way to see it working in no time.
The two minute version
If you only do one thing, do this.
npm ci && npm run build.php cli/joomla.php scheduler:run if you prefer the CLI.The article is now Published, and nobody clicked anything. Everything below is detail untop of that.
The rule itself

A rule lives on a transition, not on an article. It fires either after a delay counted from the moment an item entered the stage, or on a cron schedule.
Run as is the part worth poking at. The transition executes as that user with exactly their permissions, so the rule can never do something that user could not do by hand. Try setting a run-as user who lacks permission for that transition and watch it refuse rather than silently succeed. A super user can pick anyone; anyone else can only keep the user already stored on the rule, or pick themselves.
Choosing which items it applies to

Two separate questions, kept separate on purpose. A filter decides which items the rule applies to. A condition decides whether now is the right moment to fire.
Eight checks are built in: category, tag, author group, hits, day of week, date, days in stage, days since last edited. By default they are joined with AND and that is all the interface shows. OR, Not and nested groups live behind an Expert Mode switch in the Workflow Automation plugin, because most people never need them.


Preview is the bit I would most like tested. It lists the items your filter currently matches, before you save.
Seeing what is queued


Every workflow has an Upcoming Transitions tab, and there is a site-wide list with workflow and stage fitlers and paging. These are computed live rather than stored, so they cannot drift out of sync with the rules.
Articles also carry a badge in the list, and the same information appears in the sidebar when you edit one.
If you need more power


Turning on Expert Mode in the Workflow Automation plugin unlocks OR, Not and nested groups in the same builder. It is off by default because most rules never need it, and a simple rule is easier to get right. A rule that already uses those constructs always opens in the full builder, so switching the option off never hides part of a rule you have saved.
Seeing what happened

Every run is logged with an exit code: succeeded, refused, skipped, or failed. A failure records why, holds the item back instead of retrying it forever, and is reported through the existing task notification plugin.
To see a failure on purpose: as a super user, set Run as to an account that has no permission for that transition, for example a Registered user. The scheduler then refuses the transition and records the reason in the log.
If you are testing as anything other than a super user you will not be able to reproduce this, since the picker only offers you yourself or the user already stored on the rule.
Things worth trying to break
#__workflow_associations.What it deliberately does not do
Per-article, scheduling was in the original proposal and was dropped: rules live on transitions only, so there is on place to look when something unexpectedly. Loop support was dropped for the same reason.
Questions are welcome.
Placeholders in fields that disappear are generally considered to be bad for accessibility and should be avoided (https://www.nngroup.com/articles/form-design-placeholders/)
This is especially true for this field where it is hard to tell that the hint is
/5 * * * *
and not
/5**

Placeholders in fields that disappear are generally considered to be bad for accessibility and should be avoided (https://www.nngroup.com/articles/form-design-placeholders/)
This is especially true for this field where it is hard to tell that the hint is
*/5 * * * *
and not
*/5****

Thanks for the in-depth review @brianteeman
All comments have been addressed.
Quick question on the custom CSS point though, could you say which element you had in mind? I have dropped text-muted throughout the builder, but I would rather remove the right class than guess and break a layout.
Two notes. Testing the save-error report turned up a second bug: the form stored whichever fields were posted, and since showon hides an input without stopping it from submitting, a delay rule kept the last cron expression typed, valid or not. So the form itself could write a row that would not parse. Fixed in the same commit.
On the Expert Mode modal, I left off data-reload-on-close. Core uses it from list views, but this opens from inside the transition edit form and reloading would discard unsaved work. The trade-off is that the builder only picks up the new setting on the next load. Happy to change it if you would rather match the pattern exactly.
Thanks for the in-depth review @brianteeman
All comments have been addressed.
Quick question on the custom CSS point though, could you say which element you had in mind? I have dropped text-muted throughout the builder, but I would rather remove the right class than guess and break a layout.
Two notes. Testing the save-error report turned up a second bug: the form stored whichever fields were posted, and since showon hides an input without stopping it from submitting, a delay rule kept the last cron expression typed, valid or not. So the form itself could write a row that would not parse. Fixed in the same commit.
The Expert Mode link uses the same data-joomla-dialog pattern, including data-reload-on-close.
I have dropped text-muted throughout the builder,
I am still seeing text-muted
Thanks for the comments @brianteeman I was able to address them and I also found some other bugs and loopholes in the process which I handled as well. Please keep testing and let me know, thanks again
Create an autiomated rule with both an invalid filter AND an invalid condition and try to save
I would expect to get two error messages but I only get one
still only getting one message
I am pretty confused about this - or maybe i found a new problem?
with the sample data installed I created an automation for the publish transition
then I created a new article which by default is unpublished
after saving the article it says a transition will take place in 5 minutes

not sure why it says that because the automation is on the publish transition and this is unpublished
after waiting the required minutes nothing changes to the state of the article (which is what i expected as there was no automation on the unpublished transition) but the tooltip is updated to say due now
and in the article itself it says
I am pretty confused about this - or maybe i found a new problem?
with the sample data installed I created an automation for the publish transition
then I created a new article which by default is unpublished
after saving the article it says a transition will take place in 5 minutes

not sure why it says that because the automation is on the publish transition and this is unpublished
after waiting the required minutes nothing changes to the state of the article (which is what i expected as there was no automation on the unpublished transition) but the tooltip is updated to say due now
and in the article itself it says
now i am really confused - after returning some time later these articles are now published
Create an autiomated rule with both an invalid filter AND an invalid condition and try to save
I would expect to get two error messages but I only get onestill only getting one message
@brianteeman both errors are raised, but core keeps only one. FormField::validate() applies SubformRule to any subform field automatically, and SubformRule::test() returns $errors[0] and discards the rest, at [SubformRule.php:66] and again at line 79. The comment there says as much: "Pass the first error that occurred on the subform validation."
The filter and condition builders both live in the automation subform, so from the parent form's point of view they are one field and can carry one error. The message does name which builder is at fault and marks that field, so fixing it and saving surfaces the next one.
I could collect both into a single combined sentence by validating at the subform level instead, but then the error attaches to the whole subform rather than the builder that is wrong, which loses the field marking. That seemed a worse trade, but please let me know if that would be better
Thanks @brianteeman please take a look and let me know if anything else comes up.
I cant comment on the way that the code displays the error. I can only comment that you should display all errors
I cant comment on the way that the code displays the error. I can only comment that you should display all errors
Got it @brianteeman I just made some changes. Please test again and let me know how it goes, thanks!
This is a new feature so should be made against the 6.3-dev branch not the 6.2 branch