Releases: breonwilliams/flowmint-workflows
Release list
FlowMint Workflows v0.7.0
- Added: workflow emails and messages can now use the option LABEL a visitor actually chose, not the value stored behind it.
{{ labels.workshop }}writes "Hand-Cut Joinery Intensive" where{{ data.workshop }}writes "joinery". Machine steps keep using the raw value, so nothing existing changes. - Fixed: uploaded-file details in workflows are now documented as they actually behave — keyed by field name, with no file URL, and a shape that changes when more than one file is attached. Each of those failed silently before, producing a workflow that reported success while sending nothing.
- Fixed: the connector could not reach an HTTPS local development site.
v0.6.8
Connector setup: the Copy Command button now sits below the code block instead of overlaying it, fixing an overlap and a color-contrast issue.
FlowMint Workflows v0.6.7
Adds AGENTS.md developer/AI reference documentation. No functional changes.
v0.6.6
Changelog
All notable changes to FlowMint Workflows will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[0.6.6] — 2026-07-11
Fixed
- Plugin Check compliance sweep (2026-07-11). Added the required
translators:comments to the failure notifier's placeholder-bearing__()calls; raisedRequires at leastfrom 5.0 to 5.6 (the Cowork connector depends on the Application Passwords API, WP 5.6+, and scheduled triggers usewp_timezone(), WP 5.3+ — the header now matches reality instead of under-promising); bumpedTested up toto 7.0. (includes/Core/class-fmw-failure-notifier.php,flowmint-workflows.php,readme.txt,CLAUDE.md.)
[0.6.5] — 2026-07-04
Added
- Failure notifications.
FMW_Failure_Notifier(includes/Core/class-fmw-failure-notifier.php) listens tofmw_workflow_run_failedat priority 100 and pushes a plain-text alert when a run permanently fails (exhausts all retries): Slack incoming webhook when theslack_webhookcredential is configured (non-blocking POST, 3s timeout), otherwise email to thenotification_emailcredential falling back to the siteadmin_email— every site gets a signal out of the box. The alert carries the workflow name, error code/message, entry context, and a deep link to the run for one-click inspect/replay. Defensively wrapped so it can never break the failure path it observes; fires only after max retries so every alert is a final, human-worthy failure. Filters:fmw_failure_notification_enabled,fmw_failure_notification_message. Closes the long-documented "failed runs are only visible in the admin UI" operational gap.
Changed
bin/build-release.shnow verifies the release ZIP's internal structure after packaging (required nested paths incl.vendor/autoload.phpand Action Scheduler) and aborts on a flattened or vendor-less archive — turning the documented "Composer not on PATH → dead-on-arrival ZIP" gotcha into a hard build failure. Build tooling only; not shipped in the ZIP.- Documentation truthfulness pass:
CLAUDE.mdcorrected to shipped reality (phase table,pforms_*hook names since FRE 1.8.0, FRE 1.8.0 minimum, MCP layout, known gaps) and theFMW_DB_VERSION0.3.0 no-DDL convention documented at the constant.
[0.6.4] — 2026-06-02
Fixed
-
Conditional step took the else branch every time, regardless of the
ifexpression.FMW_Step_Conditional::execute()was reading$this->config['if']— i.e. the POST-interpolation config the executor passed in. The executor runs the entire step config throughFMW_Interpolator::interpolate()before instantiating the step, including the conditional'siffield. Since the interpolator only understands{{ context.path }}substitution and has no concept of comparison/logical operators, an expression like{{ data.urgency == 'high' }}came out as an empty string by the time it reached the conditional step.FMW_Expression::evaluate('')correctly returns false, so every conditional silently took the else branch. The previous code carried a// Workaround: ...comment in the step that explicitly admitted the implementation didn't work — it shipped anyway. Caught during pressure testing of a real urgency-routing workflow that submitted two entries with differenturgencyvalues, both produced identical branch behavior.The fix plumbs the RAW (pre-interpolation) config through alongside the interpolated one:
FMW_Step_Basegains a$raw_configproperty, populated from$step_definition['raw_config']and falling back to$this->configfor backward compat with any direct-instantiation callers.FMW_Workflow_Executorincludes'raw_config' => $raw_configin the step definition it constructs.FMW_Step_Conditionalreads$this->raw_config['if']for the expression. Comparison operators now survive into the expression evaluator, which builds its own interpolator pass to resolve the{{ context.path }}blocks correctly.FMW_Step_Conditionalalso pullsthen/elsestep arrays from raw_config when available, so a nested conditional inside athenbranch gets its owniffield un-interpolated. Without this, the nested-conditional case would reintroduce the bug at the inner level.
Notes
- No database schema changes.
FMW_DB_VERSIONunchanged at0.3.0. - No new step types, no API changes.
- Existing non-conditional workflows are unaffected — they continue to read
$this->config, which still receives the same pre-interpolated values it always has. skip_ifclauses (the FMW_Expression docblock mentions them) and thetry_catchstep both also use the expression evaluator.skip_ifwas not exercised by pressure testing and may or may not have the same drift; will be audited separately.try_catch's nestedtry/catcharrays contain step definitions that re-enter the executor, so they're not affected by this fix one way or the other.
[0.6.3] — 2026-06-02
Fixed
- Stale rename guard in workflow validator —
FMW_Workflow_Validator::validate_full()was checkingfunction_exists( 'fre' )before consulting the Promptless Forms registry to verify form_id existence. The function was renamedfre()→pforms()in PForms v1.8.0; the guard was checking the legacy name. Every form-id existence check silently fell through to the "FormEngine not loaded" warning even when Promptless Forms was present and the registry was queryable. Now checksfunction_exists( 'pforms' ). Caught during pressure testing. - Update endpoint dropped trigger inference when caller omitted form_id —
FMW_REST_Workflows::update()did not pre-fetch the existing workflow's form_id before re-validating, so a PATCH that supplied a new config without an explicit trigger block — but expected the existing form binding to be preserved per the standard REST "omitted = unchanged" contract — failed withMissing required field: trigger. Now pulls the existing form_id from the database and injects it into the validation payload, making update() symmetric with create() when both receive a config that lacks an explicit trigger.
Changed (documentation / DX)
- MCP connector descriptions corrected on step shape —
flowmint-connector.jsstep shape descriptions said{ id, type, config, on_error?, when? }but the validator requiresname, notid. Two description strings updated to{ name, type, config, on_error?, when? }so first-time workflow creates don't fail with a confusing "missing or invalid 'name'" error. Important for users on existing connector installs: the connector JS lives at~/flowmint-mcp/flowmint-connector.json each Mac, downloaded by the connector setup command. Updating the plugin does NOT update the local copy. Re-run the connector setup command from WP admin → FlowMint Workflows → Claude Connection to pull the corrected descriptions. - Preflight response now documents the workflow context shape — added a
context_shapeblock listing every top-level namespace accessible via{{ … }}interpolation (data,entry,entry_files,run,workflow,form,steps,vars), with descriptions, an example, and acommon_trapslist calling out the two patterns that produce silent empty-string substitutions:entry.fields.*(form fields are atdata.*, notentry.fields.*) andsteps.<type>.*(use the step NAME, not the type). Resolves the friction that surfaced during pressure testing ofsession_registration→session_registration_confirmation, where guessed interpolation paths produced an emptytofield in the email step and a genericconfig_error. - MCP tool description now references current names —
flowmint_create_workflowdescription previously referred to "fre_submission_complete" (the legacy hook name) and "an FRE form". Updated to "pforms_submission_complete" and "Promptless Forms" to match the v0.6.2 rename. No behavior change.
Notes
- No database schema changes.
FMW_DB_VERSIONunchanged at0.3.0. - Minimum required Promptless Forms version unchanged at 1.8.0.
- Internal symbol surface (
FMW_*classes,fmw_*actions/filters,pforms_submission_completehook listener wiring) unchanged.
[0.6.2] — 2026-06-02
Fixed
- Dependency check now treats Promptless Forms as present when either the
PForms_VERSIONconstant is defined OR thePromptless_Formsclass exists. Single-signal checks against the constant were observed to false-positive on certain managed-host environments (Bluehost's stack in testing) where the constant was not defined atadmin_noticestime despite Promptless Forms being active and the admin pages rendering correctly. The class fallback closes that gap so FlowMint stops showing a spurious "missing dependency" error when its prerequisite plugin is actually present and working. Version-compare enforcement still requires the constant — when only the class is detectable we accept "present" and let any real version mismatch surface as step-run failures in run history rather than as a blanket block.
Changed
- User-facing admin notices and the plugin Description header updated from "Form Runtime Engine" to "Promptless Forms" — Promptless Forms shipped on WordPress.org at the renamed slug in v1.8.0 and FlowMint's surface text was still pointing at the legacy name.
- Internal symbol surface (
FMW_REQUIRED_FRE_VERSIONconstant,FormEnginestep categories, internal class names referencingFre) is unchanged — those are internal-only and renaming would invalidate stored workflow JSON without behavioral benefit. Only user-visible strings were touched.
Notes
- No database schema changes;
FMW_DB_VERSIONunchanged at 0.3.0. - Minimum required Promptless Forms version unchanged at 1.8.0.
[0.6.1] — 2026-05-17
Changed
- Renamed connector admin page from "Claude Connection" to "C...
FlowMint Workflows v0.6.5
Adds failure notifications: when a workflow run permanently fails, FlowMint alerts via Slack (slack_webhook credential) or email (notification_email credential / admin email) with a deep link to inspect and replay the run. No schema or workflow changes — safe update from any 0.6.x.
v0.6.4 - fix conditional step always taking else branch
Changelog
All notable changes to FlowMint Workflows will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[0.6.4] — 2026-06-02
Fixed
-
Conditional step took the else branch every time, regardless of the
ifexpression.FMW_Step_Conditional::execute()was reading$this->config['if']— i.e. the POST-interpolation config the executor passed in. The executor runs the entire step config throughFMW_Interpolator::interpolate()before instantiating the step, including the conditional'siffield. Since the interpolator only understands{{ context.path }}substitution and has no concept of comparison/logical operators, an expression like{{ data.urgency == 'high' }}came out as an empty string by the time it reached the conditional step.FMW_Expression::evaluate('')correctly returns false, so every conditional silently took the else branch. The previous code carried a// Workaround: ...comment in the step that explicitly admitted the implementation didn't work — it shipped anyway. Caught during pressure testing of a real urgency-routing workflow that submitted two entries with differenturgencyvalues, both produced identical branch behavior.The fix plumbs the RAW (pre-interpolation) config through alongside the interpolated one:
FMW_Step_Basegains a$raw_configproperty, populated from$step_definition['raw_config']and falling back to$this->configfor backward compat with any direct-instantiation callers.FMW_Workflow_Executorincludes'raw_config' => $raw_configin the step definition it constructs.FMW_Step_Conditionalreads$this->raw_config['if']for the expression. Comparison operators now survive into the expression evaluator, which builds its own interpolator pass to resolve the{{ context.path }}blocks correctly.FMW_Step_Conditionalalso pullsthen/elsestep arrays from raw_config when available, so a nested conditional inside athenbranch gets its owniffield un-interpolated. Without this, the nested-conditional case would reintroduce the bug at the inner level.
Notes
- No database schema changes.
FMW_DB_VERSIONunchanged at0.3.0. - No new step types, no API changes.
- Existing non-conditional workflows are unaffected — they continue to read
$this->config, which still receives the same pre-interpolated values it always has. skip_ifclauses (the FMW_Expression docblock mentions them) and thetry_catchstep both also use the expression evaluator.skip_ifwas not exercised by pressure testing and may or may not have the same drift; will be audited separately.try_catch's nestedtry/catcharrays contain step definitions that re-enter the executor, so they're not affected by this fix one way or the other.
[0.6.3] — 2026-06-02
Fixed
- Stale rename guard in workflow validator —
FMW_Workflow_Validator::validate_full()was checkingfunction_exists( 'fre' )before consulting the Promptless Forms registry to verify form_id existence. The function was renamedfre()→pforms()in PForms v1.8.0; the guard was checking the legacy name. Every form-id existence check silently fell through to the "FormEngine not loaded" warning even when Promptless Forms was present and the registry was queryable. Now checksfunction_exists( 'pforms' ). Caught during pressure testing. - Update endpoint dropped trigger inference when caller omitted form_id —
FMW_REST_Workflows::update()did not pre-fetch the existing workflow's form_id before re-validating, so a PATCH that supplied a new config without an explicit trigger block — but expected the existing form binding to be preserved per the standard REST "omitted = unchanged" contract — failed withMissing required field: trigger. Now pulls the existing form_id from the database and injects it into the validation payload, making update() symmetric with create() when both receive a config that lacks an explicit trigger.
Changed (documentation / DX)
- MCP connector descriptions corrected on step shape —
flowmint-connector.jsstep shape descriptions said{ id, type, config, on_error?, when? }but the validator requiresname, notid. Two description strings updated to{ name, type, config, on_error?, when? }so first-time workflow creates don't fail with a confusing "missing or invalid 'name'" error. Important for users on existing connector installs: the connector JS lives at~/flowmint-mcp/flowmint-connector.json each Mac, downloaded by the connector setup command. Updating the plugin does NOT update the local copy. Re-run the connector setup command from WP admin → FlowMint Workflows → Claude Connection to pull the corrected descriptions. - Preflight response now documents the workflow context shape — added a
context_shapeblock listing every top-level namespace accessible via{{ … }}interpolation (data,entry,entry_files,run,workflow,form,steps,vars), with descriptions, an example, and acommon_trapslist calling out the two patterns that produce silent empty-string substitutions:entry.fields.*(form fields are atdata.*, notentry.fields.*) andsteps.<type>.*(use the step NAME, not the type). Resolves the friction that surfaced during pressure testing ofsession_registration→session_registration_confirmation, where guessed interpolation paths produced an emptytofield in the email step and a genericconfig_error. - MCP tool description now references current names —
flowmint_create_workflowdescription previously referred to "fre_submission_complete" (the legacy hook name) and "an FRE form". Updated to "pforms_submission_complete" and "Promptless Forms" to match the v0.6.2 rename. No behavior change.
Notes
- No database schema changes.
FMW_DB_VERSIONunchanged at0.3.0. - Minimum required Promptless Forms version unchanged at 1.8.0.
- Internal symbol surface (
FMW_*classes,fmw_*actions/filters,pforms_submission_completehook listener wiring) unchanged.
[0.6.2] — 2026-06-02
Fixed
- Dependency check now treats Promptless Forms as present when either the
PForms_VERSIONconstant is defined OR thePromptless_Formsclass exists. Single-signal checks against the constant were observed to false-positive on certain managed-host environments (Bluehost's stack in testing) where the constant was not defined atadmin_noticestime despite Promptless Forms being active and the admin pages rendering correctly. The class fallback closes that gap so FlowMint stops showing a spurious "missing dependency" error when its prerequisite plugin is actually present and working. Version-compare enforcement still requires the constant — when only the class is detectable we accept "present" and let any real version mismatch surface as step-run failures in run history rather than as a blanket block.
Changed
- User-facing admin notices and the plugin Description header updated from "Form Runtime Engine" to "Promptless Forms" — Promptless Forms shipped on WordPress.org at the renamed slug in v1.8.0 and FlowMint's surface text was still pointing at the legacy name.
- Internal symbol surface (
FMW_REQUIRED_FRE_VERSIONconstant,FormEnginestep categories, internal class names referencingFre) is unchanged — those are internal-only and renaming would invalidate stored workflow JSON without behavioral benefit. Only user-visible strings were touched.
Notes
- No database schema changes;
FMW_DB_VERSIONunchanged at 0.3.0. - Minimum required Promptless Forms version unchanged at 1.8.0.
[0.6.1] — 2026-05-17
Changed
- Renamed connector admin page from "Claude Connection" to "Connector" (menu) / "The FlowMint Connector" (page title) — vendor-neutral naming future-proofed for additional AI clients
- Redesigned connector page with card-based layout, clearer 3-step setup flow, and improved connection status display
- Added warning notice when Application Passwords are unavailable (requires HTTPS or
WP_ENVIRONMENT_TYPE='local')
[0.6.0] — 2026-05-15
Added — Scheduled workflow triggers
Workflows can now be triggered on a recurring schedule (hourly / twice-daily / daily / weekly) in addition to form submissions. Closes the "Scheduled workflows" item that was explicitly deferred to v2+ in docs/ROADMAP.md — the architecture left room for it, and v0.6.0 cashes that in. Full design contract: docs/DESIGN_SCHEDULED_TRIGGERS.md. User-facing guide: docs/SCHEDULED_WORKFLOWS.md.
New trigger abstraction.
- Workflow JSON gains a
triggerblock. Two trigger types in v0.6:{ type: "form", form_id: "…" }(form-triggered, the existing pattern made explicit) and{ type: "schedule", interval: "…", hour: …, minute: …, day_of_week: … }(scheduled, new). - Legacy workflows that have just a top-level
form_idcontinue to work — the validator normalizes them into the v0.6 shape transparently. Existing workflows on production sites do NOT need their JSON rewritten. - The REST API accepts the new
triggerblock at the wrapper level for convenience (alongsideid,title,config), or inside the config JSON. Preflight reportssupported_trigger_types: ["form", "schedule"]so MCP clients can introspect capabilities.
New step types (FormEngine category).
fre_list_entries— Query FE entries by form, status, and/or age. Backed byFRE_Entry_Query(FRE 1.6.0+). Hard cap of 1000 rows per call. Returns oldest-first. Output includes ahit_limitflag so the next tick can pick up the overflow.fre_delete_entries— Bulk-delete by ID list (accepts entry objects fromfre_list_entriesOR bare integer IDs). Idempotent — re-running on already-deleted IDs returnsalready_gonerather than erroring. Per-id failure tolerance — one bad entry doesn't sink the batch; fail...
v0.6.3 - DX fixes from pressure testing
Changelog
All notable changes to FlowMint Workflows will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[0.6.3] — 2026-06-02
Fixed
- Stale rename guard in workflow validator —
FMW_Workflow_Validator::validate_full()was checkingfunction_exists( 'fre' )before consulting the Promptless Forms registry to verify form_id existence. The function was renamedfre()→pforms()in PForms v1.8.0; the guard was checking the legacy name. Every form-id existence check silently fell through to the "FormEngine not loaded" warning even when Promptless Forms was present and the registry was queryable. Now checksfunction_exists( 'pforms' ). Caught during pressure testing. - Update endpoint dropped trigger inference when caller omitted form_id —
FMW_REST_Workflows::update()did not pre-fetch the existing workflow's form_id before re-validating, so a PATCH that supplied a new config without an explicit trigger block — but expected the existing form binding to be preserved per the standard REST "omitted = unchanged" contract — failed withMissing required field: trigger. Now pulls the existing form_id from the database and injects it into the validation payload, making update() symmetric with create() when both receive a config that lacks an explicit trigger.
Changed (documentation / DX)
- MCP connector descriptions corrected on step shape —
flowmint-connector.jsstep shape descriptions said{ id, type, config, on_error?, when? }but the validator requiresname, notid. Two description strings updated to{ name, type, config, on_error?, when? }so first-time workflow creates don't fail with a confusing "missing or invalid 'name'" error. Important for users on existing connector installs: the connector JS lives at~/flowmint-mcp/flowmint-connector.json each Mac, downloaded by the connector setup command. Updating the plugin does NOT update the local copy. Re-run the connector setup command from WP admin → FlowMint Workflows → Claude Connection to pull the corrected descriptions. - Preflight response now documents the workflow context shape — added a
context_shapeblock listing every top-level namespace accessible via{{ … }}interpolation (data,entry,entry_files,run,workflow,form,steps,vars), with descriptions, an example, and acommon_trapslist calling out the two patterns that produce silent empty-string substitutions:entry.fields.*(form fields are atdata.*, notentry.fields.*) andsteps.<type>.*(use the step NAME, not the type). Resolves the friction that surfaced during pressure testing ofsession_registration→session_registration_confirmation, where guessed interpolation paths produced an emptytofield in the email step and a genericconfig_error. - MCP tool description now references current names —
flowmint_create_workflowdescription previously referred to "fre_submission_complete" (the legacy hook name) and "an FRE form". Updated to "pforms_submission_complete" and "Promptless Forms" to match the v0.6.2 rename. No behavior change.
Notes
- No database schema changes.
FMW_DB_VERSIONunchanged at0.3.0. - Minimum required Promptless Forms version unchanged at 1.8.0.
- Internal symbol surface (
FMW_*classes,fmw_*actions/filters,pforms_submission_completehook listener wiring) unchanged.
[0.6.2] — 2026-06-02
Fixed
- Dependency check now treats Promptless Forms as present when either the
PForms_VERSIONconstant is defined OR thePromptless_Formsclass exists. Single-signal checks against the constant were observed to false-positive on certain managed-host environments (Bluehost's stack in testing) where the constant was not defined atadmin_noticestime despite Promptless Forms being active and the admin pages rendering correctly. The class fallback closes that gap so FlowMint stops showing a spurious "missing dependency" error when its prerequisite plugin is actually present and working. Version-compare enforcement still requires the constant — when only the class is detectable we accept "present" and let any real version mismatch surface as step-run failures in run history rather than as a blanket block.
Changed
- User-facing admin notices and the plugin Description header updated from "Form Runtime Engine" to "Promptless Forms" — Promptless Forms shipped on WordPress.org at the renamed slug in v1.8.0 and FlowMint's surface text was still pointing at the legacy name.
- Internal symbol surface (
FMW_REQUIRED_FRE_VERSIONconstant,FormEnginestep categories, internal class names referencingFre) is unchanged — those are internal-only and renaming would invalidate stored workflow JSON without behavioral benefit. Only user-visible strings were touched.
Notes
- No database schema changes;
FMW_DB_VERSIONunchanged at 0.3.0. - Minimum required Promptless Forms version unchanged at 1.8.0.
[0.6.1] — 2026-05-17
Changed
- Renamed connector admin page from "Claude Connection" to "Connector" (menu) / "The FlowMint Connector" (page title) — vendor-neutral naming future-proofed for additional AI clients
- Redesigned connector page with card-based layout, clearer 3-step setup flow, and improved connection status display
- Added warning notice when Application Passwords are unavailable (requires HTTPS or
WP_ENVIRONMENT_TYPE='local')
[0.6.0] — 2026-05-15
Added — Scheduled workflow triggers
Workflows can now be triggered on a recurring schedule (hourly / twice-daily / daily / weekly) in addition to form submissions. Closes the "Scheduled workflows" item that was explicitly deferred to v2+ in docs/ROADMAP.md — the architecture left room for it, and v0.6.0 cashes that in. Full design contract: docs/DESIGN_SCHEDULED_TRIGGERS.md. User-facing guide: docs/SCHEDULED_WORKFLOWS.md.
New trigger abstraction.
- Workflow JSON gains a
triggerblock. Two trigger types in v0.6:{ type: "form", form_id: "…" }(form-triggered, the existing pattern made explicit) and{ type: "schedule", interval: "…", hour: …, minute: …, day_of_week: … }(scheduled, new). - Legacy workflows that have just a top-level
form_idcontinue to work — the validator normalizes them into the v0.6 shape transparently. Existing workflows on production sites do NOT need their JSON rewritten. - The REST API accepts the new
triggerblock at the wrapper level for convenience (alongsideid,title,config), or inside the config JSON. Preflight reportssupported_trigger_types: ["form", "schedule"]so MCP clients can introspect capabilities.
New step types (FormEngine category).
fre_list_entries— Query FE entries by form, status, and/or age. Backed byFRE_Entry_Query(FRE 1.6.0+). Hard cap of 1000 rows per call. Returns oldest-first. Output includes ahit_limitflag so the next tick can pick up the overflow.fre_delete_entries— Bulk-delete by ID list (accepts entry objects fromfre_list_entriesOR bare integer IDs). Idempotent — re-running on already-deleted IDs returnsalready_gonerather than erroring. Per-id failure tolerance — one bad entry doesn't sink the batch; failures land in afailedarray.
Database schema (v0.2.0 migration).
wp_fmw_workflows.form_idis now NULLABLE (scheduled workflows have no bound form).- New
wp_fmw_workflows.trigger_typecolumn (VARCHAR(32) NOT NULL DEFAULT 'form') indexed via new composite keyidx_trigger_type (trigger_type, enabled)for efficient "find all enabled scheduled workflows" lookups byFMW_Schedule_Listener. - Migration is additive, idempotent, and probes column / index state via
SHOW COLUMNS/SHOW INDEXbefore each ALTER. Existing rows are correctly classified astrigger_type = 'form'by the column default. Rollback to v0.5.0 does NOT require dropping the new column — the older code simply ignores it.
New class: FMW_Schedule_Listener (includes/Core/class-fmw-schedule-listener.php).
- Mirrors
FMW_Submission_Listenerbut for the scheduled trigger path. - Subscribes to
fmw_workflow_saved/fmw_workflow_disabled/fmw_workflow_deleted(newly fired by the repository) — registers an Action Scheduler recurring event when a scheduled workflow is saved + enabled, unregisters when it's disabled or deleted. - Tick handler creates a queued run via
FMW_Run_Repository::create_pending_scheduled(form_id = '',entry_id = 0sentinels per design §5.2), then enqueuesfmw_run_workflowasync action — same downstream path as form submissions. - Timezone-aware first-tick computation:
dailyandweeklyintervals use site-local time (wp_timezone()), matching howSettings → Generaldisplays "site timezone."
Daily reconciliation pass.
- New AS recurring action
fmw_reconcile_scheduled_eventsfires daily and reconciles AS recurring events with the workflows table. Drift correction: even if an AS action was lost or wiped, the next reconciliation rebuilds it. - Bootstrap is self-healing: on the first plugins_loaded after v0.6.0 lands, schedules the daily reconciliation AND runs an immediate pass so any pre-existing scheduled workflows get their cron events without a 24h wait. Hooked on
initpriority 20 (after AS's data store initialization atinitpriority 1).
Validator additions.
FMW_Workflow_Validator::normalize()— public static method that converts legacy → v0.6 shape on a copy. Idempotent.triggerblock validation: enum-checkedtype('form' | 'schedule'), enum-checkedinterval('hourly' | 'twicedaily' | 'daily' | 'weekly'), range-checkedhour(0–23),minute(0–59),day_of_week(1–7 ISO-8601).- New warning (not error) for scheduled workflows that interpolate
{{ data.* }}/{{ entry.* }}/{{ entry_files.* }}— scheduled runs have no FE entry context, so those referenc...
v0.6.2 - dependency check + Promptless Forms text cleanup
Changelog
All notable changes to FlowMint Workflows will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[0.6.2] — 2026-06-02
Fixed
- Dependency check now treats Promptless Forms as present when either the
PForms_VERSIONconstant is defined OR thePromptless_Formsclass exists. Single-signal checks against the constant were observed to false-positive on certain managed-host environments (Bluehost's stack in testing) where the constant was not defined atadmin_noticestime despite Promptless Forms being active and the admin pages rendering correctly. The class fallback closes that gap so FlowMint stops showing a spurious "missing dependency" error when its prerequisite plugin is actually present and working. Version-compare enforcement still requires the constant — when only the class is detectable we accept "present" and let any real version mismatch surface as step-run failures in run history rather than as a blanket block.
Changed
- User-facing admin notices and the plugin Description header updated from "Form Runtime Engine" to "Promptless Forms" — Promptless Forms shipped on WordPress.org at the renamed slug in v1.8.0 and FlowMint's surface text was still pointing at the legacy name.
- Internal symbol surface (
FMW_REQUIRED_FRE_VERSIONconstant,FormEnginestep categories, internal class names referencingFre) is unchanged — those are internal-only and renaming would invalidate stored workflow JSON without behavioral benefit. Only user-visible strings were touched.
Notes
- No database schema changes;
FMW_DB_VERSIONunchanged at 0.3.0. - Minimum required Promptless Forms version unchanged at 1.8.0.
[0.6.1] — 2026-05-17
Changed
- Renamed connector admin page from "Claude Connection" to "Connector" (menu) / "The FlowMint Connector" (page title) — vendor-neutral naming future-proofed for additional AI clients
- Redesigned connector page with card-based layout, clearer 3-step setup flow, and improved connection status display
- Added warning notice when Application Passwords are unavailable (requires HTTPS or
WP_ENVIRONMENT_TYPE='local')
[0.6.0] — 2026-05-15
Added — Scheduled workflow triggers
Workflows can now be triggered on a recurring schedule (hourly / twice-daily / daily / weekly) in addition to form submissions. Closes the "Scheduled workflows" item that was explicitly deferred to v2+ in docs/ROADMAP.md — the architecture left room for it, and v0.6.0 cashes that in. Full design contract: docs/DESIGN_SCHEDULED_TRIGGERS.md. User-facing guide: docs/SCHEDULED_WORKFLOWS.md.
New trigger abstraction.
- Workflow JSON gains a
triggerblock. Two trigger types in v0.6:{ type: "form", form_id: "…" }(form-triggered, the existing pattern made explicit) and{ type: "schedule", interval: "…", hour: …, minute: …, day_of_week: … }(scheduled, new). - Legacy workflows that have just a top-level
form_idcontinue to work — the validator normalizes them into the v0.6 shape transparently. Existing workflows on production sites do NOT need their JSON rewritten. - The REST API accepts the new
triggerblock at the wrapper level for convenience (alongsideid,title,config), or inside the config JSON. Preflight reportssupported_trigger_types: ["form", "schedule"]so MCP clients can introspect capabilities.
New step types (FormEngine category).
fre_list_entries— Query FE entries by form, status, and/or age. Backed byFRE_Entry_Query(FRE 1.6.0+). Hard cap of 1000 rows per call. Returns oldest-first. Output includes ahit_limitflag so the next tick can pick up the overflow.fre_delete_entries— Bulk-delete by ID list (accepts entry objects fromfre_list_entriesOR bare integer IDs). Idempotent — re-running on already-deleted IDs returnsalready_gonerather than erroring. Per-id failure tolerance — one bad entry doesn't sink the batch; failures land in afailedarray.
Database schema (v0.2.0 migration).
wp_fmw_workflows.form_idis now NULLABLE (scheduled workflows have no bound form).- New
wp_fmw_workflows.trigger_typecolumn (VARCHAR(32) NOT NULL DEFAULT 'form') indexed via new composite keyidx_trigger_type (trigger_type, enabled)for efficient "find all enabled scheduled workflows" lookups byFMW_Schedule_Listener. - Migration is additive, idempotent, and probes column / index state via
SHOW COLUMNS/SHOW INDEXbefore each ALTER. Existing rows are correctly classified astrigger_type = 'form'by the column default. Rollback to v0.5.0 does NOT require dropping the new column — the older code simply ignores it.
New class: FMW_Schedule_Listener (includes/Core/class-fmw-schedule-listener.php).
- Mirrors
FMW_Submission_Listenerbut for the scheduled trigger path. - Subscribes to
fmw_workflow_saved/fmw_workflow_disabled/fmw_workflow_deleted(newly fired by the repository) — registers an Action Scheduler recurring event when a scheduled workflow is saved + enabled, unregisters when it's disabled or deleted. - Tick handler creates a queued run via
FMW_Run_Repository::create_pending_scheduled(form_id = '',entry_id = 0sentinels per design §5.2), then enqueuesfmw_run_workflowasync action — same downstream path as form submissions. - Timezone-aware first-tick computation:
dailyandweeklyintervals use site-local time (wp_timezone()), matching howSettings → Generaldisplays "site timezone."
Daily reconciliation pass.
- New AS recurring action
fmw_reconcile_scheduled_eventsfires daily and reconciles AS recurring events with the workflows table. Drift correction: even if an AS action was lost or wiped, the next reconciliation rebuilds it. - Bootstrap is self-healing: on the first plugins_loaded after v0.6.0 lands, schedules the daily reconciliation AND runs an immediate pass so any pre-existing scheduled workflows get their cron events without a 24h wait. Hooked on
initpriority 20 (after AS's data store initialization atinitpriority 1).
Validator additions.
FMW_Workflow_Validator::normalize()— public static method that converts legacy → v0.6 shape on a copy. Idempotent.triggerblock validation: enum-checkedtype('form' | 'schedule'), enum-checkedinterval('hourly' | 'twicedaily' | 'daily' | 'weekly'), range-checkedhour(0–23),minute(0–59),day_of_week(1–7 ISO-8601).- New warning (not error) for scheduled workflows that interpolate
{{ data.* }}/{{ entry.* }}/{{ entry_files.* }}— scheduled runs have no FE entry context, so those references silently resolve to empty string at runtime; the warning surfaces the typo at save time.
Job handler.
FMW_Workflow_Job::build_context()recognizes the scheduled-run sentinel (entry_id === 0) and skips the FE entry fetch entirely. The context'sentry,data,entry_filesstay empty arrays; the interpolator already handles missing variables by returning empty string, so existing step implementations continue to work unchanged.
Repository.
FMW_Workflow_Repository::create/updatenow normalize config and persisttrigger_typecolumn, allow NULLform_idfor scheduled workflows.- New
FMW_Workflow_Repository::get_all_by_trigger_type($type, $args)for the listener's reconciliation pass. get_for_form()tightened with explicittrigger_type = 'form'filter — a misconfigured scheduled workflow that somehow has a non-NULLform_idcan never be picked up by the FRE submission listener as if it were form-triggered.- Repository now fires
fmw_workflow_saved(on create + update),fmw_workflow_disabled(on enabled 1→0 transition), andfmw_workflow_deleted(on delete) actions.
REST.
/workflowslist endpoint accepts atrigger_typequery parameter./preflightreportssupported_trigger_types.- All other endpoints accept the new
triggerblock in request bodies and return it in responses. Backwards-compat for legacyform_idat the wrapper level: still works, still normalized totrigger.type = "form"internally.
Verification (local Flywheel site).
99 of 99 smoke checks green across three layered test suites:
- Phase 1 (32 checks) — schema migration, value-object accessors, validator normalization + trigger validation, repository scheduled + legacy create/retrieve, lifecycle hooks fire correctly, schedule listener stub is a no-op.
- Phase 2 (32 checks) — listener wiring, AS event registration on save/update/disable/delete, end-to-end tick → run completes synchronously, reconciliation drift correction, form-triggered regression unaffected.
- Phase 3 (35 checks) — both new step types registered with correct metadata, every documented filter combination on
fre_list_entries, idempotency + mixed-input tolerance onfre_delete_entries, end-to-end retention workflow scenario with the actual 725 use case JSON.
Plugin version stamp: 0.6.0 — stable release following 725 Print Lab production verification.
[0.5.0] — 2026-05-10
Added — Claude Cowork MCP connector
Closes the Critical C2 finding in FLOWMINT_AUDIT.md: the WordPress-side REST connector at flowmint/v1/connector/* had been built in v0.3.0, but the client-side MCP bridge that lets Claude Desktop reach those endpoints was missing. This release ships the bridge.
New files
includes/Connectors/MCP/assets/flowmint-connector.js— single-file Node.js stdio MCP server. Exposes 16 tools (preflight, full workflow CRUD, run history + replay, step type catalog, credential introspection + test, template read). Maps 1:1 to the existing REST endpoints. Forked from the Form Runtime Engine connector with FlowMint-specific tool definitions and route paths.includes/Connectors/MCP/class-fmw-connector-admin.php—FlowMint Workflows → Claude Connectionadmin page. Generates and revokes ...
v0.6.1
Connector admin page UI polish. See CHANGELOG.md for details.
Changed
- Renamed connector admin page from "Claude Connection" to "Connector" (menu) / "The FlowMint Connector" (page title) — vendor-neutral naming future-proofed for additional AI clients
- Redesigned connector page with card-based layout, clearer 3-step setup flow, and improved connection status display
- Added warning notice when Application Passwords are unavailable (requires HTTPS or
WP_ENVIRONMENT_TYPE='local')
v0.6.0
Scheduled Workflow Triggers
v0.6.0 adds scheduled workflow triggers as a first-class capability. Workflows can now fire on a recurring schedule (hourly / twicedaily / daily / weekly) in addition to form submissions.
Highlights
- New trigger abstraction — Workflow JSON gains a
triggerblock with two types:form(existing pattern) andschedule(new) - New step types —
fre_list_entriesandfre_delete_entriesfor bulk querying and deleting FormEngine entries - Daily reconciliation — Self-healing AS recurring action ensures scheduled workflows stay registered even if AS data is cleared
- Database schema v0.2.0 — Additive migration (nullable
form_id+ newtrigger_typecolumn); existing workflows unaffected
Production Verified
99/99 smoke checks green across three layered test suites. 725 Print Lab production verification complete.
See CHANGELOG.md for full details, or the user guide at docs/SCHEDULED_WORKFLOWS.md.