Changelog

What changed in each release of PromptWire.

1.12.1 (22 May 2026)

  • Fixed: pw_file_sync now reads local files from ids.local.id, not meta.pageId. After a remote pull, pageId in meta reflects the remote environment — local binaries live under a different id. The sync no longer silently reports zero local files when id drift is present.
  • Fixed: pw_file_sync passes file description from page.yaml to file:upload, and re-syncs when the binary is unchanged but the description differs (metadataOnly upload).
  • Fixed: file:upload removes on-disk orphans before replacing a file, preventing ProcessWire from suffixing replacements (for example mediahub-1_17_0-1.zip).
  • New: file:upload supports metadataOnly: true to update a file description without re-uploading the binary.
  • Fixed: pw_page_push / page:update apply file field descriptions from YAML (metadata only — binaries still sync via pw_file_sync). Previously dry-run reported description changes that were never applied.
  • Fixed: Remote page:update applies file description arrays when pushed from the MCP server.
  • Changed: files:push allows promptwire-api.php at the site root so the remote API endpoint can be deployed via the existing push tooling. New script: scripts/push-api-to-remote.mjs.
  • Migration impact: zero for callers. Existing workflows gain correct behaviour; no signature changes.

1.12.0 (11 May 2026)

  • Default-changed: pw_site_sync no longer pushes site/modules/* unless asked. Every sync run now prepends site/modules/* to the effective excludeFilePatterns and skips module code in the file step. To ship a plugin update alongside templates/content, pass the new pushModules: true flag. Dry-run plans surface a files.modulesExcluded block when the auto-exclusion is in effect.
  • Fixed: pw_health.writesEnabled is no longer a hardcoded false. Now computed from the actual gate state: CLI invocations report true with reason cli; web invocations report true with reason api-key (plus +ip-allowlist or +http when those gates apply). A sibling writesEnabledReason field carries the breakdown.
  • Migration impact: pw_site_sync callers that relied on module pushes by default must add pushModules: true. Anything scripting against writesEnabled === false will now see true on correctly configured installs.

1.11.1 (1 May 2026)

  • New: Frontend-usage scan on remove operations. Before pw_template_fields_push removes a field from a template's fieldgroup, it scans site/templates/ for hardcoded references to the field name (in .php, .module, .inc, and .html files) and emits a warning listing file paths, line numbers, and snippets when any match. Complements v1.11.0's module-ownership awareness: that catches fields belonging to known modules; this catches the broader case where a regular field like your_email or feedback is hardcoded in a custom contact form's PHP. Removing the field would leave ProcessWire healthy but silently no-op the assignment, so the form stops working with no admin-side error.
  • Implementation note: The scan is fail-open on every error path (missing templates dir, FS permission, iterator exception) and capped at 200 files / 2.0s wallclock so it can never block the classifier. Word-boundary matching keeps substring false positives out (blog_ does not match blog_date). Warning, not danger, because the removal may be a legitimate cleanup, the operator gets full visibility without being blocked.
  • Migration impact: zero. Strictly additive on the warnings array. No existing tool's signature or output changes.

1.11.0 (1 May 2026)

  • New: pw_template_fields_push tool. The first tool in the fieldgroup-edit family. Adds, removes, and reorders fields on a template's fieldgroup, and sets per-fieldgroup context overrides (label override, description, required, columnWidth, showIf, requiredIf, collapsed, plus the FieldtypePage-specific keys like template_id, parent_id, findPagesSelector, and inputfield). It explicitly does not modify field definitions: fieldtype changes, inputfield class swaps, and parent pickers belong to the upcoming pw_field_push in v1.12. Default dryRun: true.
  • New: Three-tier conflict classifier. Every planned change is tagged safe, warning, or danger. Dangers block the write unless force: true is also passed; warnings are visible but non-blocking. The classifier flags removals of system or permanent core fields (title, pass, roles, etc.), edits to module-owned templates (FormBuilder, Repeater storage, ProcessWire admin/user/role/permission, MediaHub, ProFields), removal of fields required on the current template, broken fieldset open/close pairs, and incomplete additions (e.g. a Page reference with no selectable-pages constraint).
  • New: Cross-site fieldtype-drift detection. When called with site: "both", the MCP layer compares the projected post-push state on each side and refuses to proceed if a field would exist on both with a different fieldtype (for example, FieldtypeCroppableImage3 locally vs FieldtypeImage on production). Drift is surfaced as a top-level crossSite block alongside the per-side results.
  • New: Audit trail on writes. Every response includes { removed, added, contextSet, reordered, saves }, populated even when a later step throws, so partial-applied writes are visible and recovery is straightforward.
  • Migration impact: zero. Strictly additive across CLI, MCP, and response shapes. No existing tool's signature or output changes.

1.10.2 (1 May 2026)

  • New: pw_page_assets compare and the pageAssets section of pw_site_compare now report an idDriftPages array alongside the existing counter. Previously, pages with divergent local/remote ids but identical assets never appeared in the diff (early-continue path), so the counter was the only signal they existed. Now the operator can see exactly which pages are drifting and decide whether the divergence is benign (organic id-sequence drift between independent installs) or a real correctness issue.
  • New: scripts/push-module-to-remote.mjs, a generalised companion to push-self-to-remote.mjs for pushing any third-party module to a PromptWire-equipped remote. Takes --source=<path> and --prefix=<site/modules/NAME/> arguments, plus an --exclude flag for skipping internal docs and test fixtures. First real-world use was aligning MediaHub 1.15.3 to 1.15.4 on production.
  • Migration impact: zero. idDriftPages is strictly additive on the result shape.

1.10.1 (30 April 2026)

  • New: Per-environment ids block in page.meta.json. Each pull populates only its own slot (ids.local or ids.remote); the other side's slot is preserved verbatim. Closes the v1.10.0 gap where re-pulling from the other environment silently overwrote meta.pageId and made the next push address the wrong page. The legacy top-level pageId is kept as a back-compat mirror.
  • Changed: pushPage is now path-first with id verification. Pages are resolved by canonical PW path; the last-seen id in the meta is used as a sanity check. If the path now resolves to a different id (page deleted and recreated, slug rebound, meta from a different site), the push is refused with a structured error and a hint to use force: true if the operator really means to push to the new id.
  • Changed: The MCP-side pull merges the remote payload with the existing local meta instead of overwriting it, so a remote pull no longer destroys local id state. pushPage and publishPage now record ids.remote after a successful live remote operation.
  • Migration impact: zero for callers. Older metas keep working; the first write on v1.10.1 or later adds the ids block.

1.10.0 (30 April 2026)

  • New: pw_page_assets tool. Syncs the on-disk asset directory for a page (site/assets/files/{pageId}/) between local and remote. Catches both standard FieldtypeFile and FieldtypeImage uploads and module-managed files (notably MediaHub, plus any custom uploader that stores files keyed by page id). The previous pw_file_sync only iterated a page's fieldgroup, so files placed in the page-asset directory by modules outside the normal field flow were silently missed. Supports inventory, download, upload, delete, and compare actions, both directions, and is dry-run by default. PW image variations (name.WxH.ext) are filtered out by default because they are regenerated on demand.
  • Changed: Pages are matched by canonical PW path, then each side resolves its own pageId from that path before walking its own asset directory. Local 1234 and remote 5678 may both legitimately resolve to /about/, normal for two sites that started from independent fresh installs. Every result reports localPageId, remotePageId, and an idDrift boolean.
  • Changed: pw_site_compare gains a pageAssets section alongside pages, schema, and files, with a per-page summary of changed, localOnly, and remoteOnly files. pw_site_sync's page-files step is replaced with a directory-walking variant that catches MediaHub-style files. The previous remote-to-local gap (a no-op with a "use SFTP" warning) is closed: pulls now fetch each missing or changed file via page-assets:download.
  • Changed: page.meta.json now embeds a pageAssets snapshot at pull time (relative path, size, md5, plus a directory hash, asset count, and total bytes). Subsequent pw_page_assets results include a driftSinceLastPull block that compares the snapshot baseline against the live inventory. Answers "what has changed in production since I last pulled?" without a fresh remote round-trip.

1.9.3 (30 April 2026)

  • Fixed: File inventories no longer descend into .git, .svn, .hg, .cursor, .vscode, .idea, node_modules, __pycache__, .next, or .cache directories. Previously, a file under one of these that happened to match the inventory's extension whitelist (for example, an IDE artifact stored inside a checked-out module's .git directory) could appear in pw_site_sync, pw_site_compare, and pw_search_files results, and could be accidentally pushed to production unless you remembered to pass excludeFilePatterns. The exclusion is now hardcoded at the directory-iterator level, so version-control metadata and IDE state can never appear in a deploy plan.
  • Performance: Pruning at the iterator level rather than filtering after the fact means .git/objects/pack/* and node_modules/ trees are no longer walked at all. Inventory generation is faster on sites with developer-installed module clones.
  • Note: vendor/ is intentionally not in the prune list, because some sites rely on file sync to ship Composer dependencies. If you need to skip it on a particular site, add it via excludeFilePatterns.

1.9.2 (30 April 2026)

  • Fixed: Deploy script no longer uploads repository documentation (ROADMAP.md, README.md, CHANGELOG.md, internal session notes) to the production module directory, where ProcessWire does not read them.

1.9.1 (30 April 2026)

  • Fixed: pw_modules_list with no classes filter no longer returns null class names. The default call now returns every installed module with a populated class field.

1.9.0 (30 April 2026)

  • New: pw_modules_list tool. Lists installed modules with version, file path, and install state. Pass site: "both" to compare local and production install state in one call.
  • New: pw_users_list tool. Lists users with id, name, email, roles, and any member_* fields. Pass includeAll: true for every non-system field on the user template. Password hashes are always excluded.
  • New: pw_resolve tool for bulk name-to-id lookup across fields, templates, pages, roles, permissions, users, or modules. Translates names into the equivalent IDs on the target site in a single call, useful before pushing changes that touch IDs which differ across environments.
  • New: pw_inspect_template tool. Like pw_get_template but each field comes back as {name, type, label}, sized for spotting fieldgroup differences (e.g. a field that is FieldtypeImage on one environment and FieldtypeCroppableImage3 on another) before pushing changes.

1.8.4 (30 April 2026)

  • Fixed: pw_site_compare no longer reports phantom diffs. Page content is now hashed deterministically across environments, so identical content produces identical hashes regardless of timezone formatting, page-array storage order, or whether a date field has an output format set. Expect a one-time wave of "modified" pages on the first compare after upgrading both sides, then it settles and any remaining diffs are real.

1.8.3 (30 April 2026)

  • New: pw_page_pull gains source: "local" | "remote". With source: "remote", a page that was edited directly in the production admin is fetched over HTTPS and written into your local sync tree, so you can re-edit and push back without touching the live admin.

1.8.2 (30 April 2026)

  • New: pw_pages_push gains targets: "local" | "remote" | "both". Pages are pushed in parent-first order so any newly-created parents exist before their children try to attach. Removes the manual page-by-page loop previously needed for bulk migrations.

1.8.1 (30 April 2026)

  • Fixed: Diagnostic tools now actually run against the remote site when asked. Previously site: "remote" was silently ignored and tools like pw_db_query always queried the local database. Eight read tools (pw_health, pw_db_schema, pw_db_query, pw_db_explain, pw_db_counts, pw_logs, pw_last_error, pw_clear_cache) now accept site: "local" | "remote" | "both". With "both", the call runs in parallel against both environments and returns both results in one round trip, useful for spotting drift.

1.8.0 (30 April 2026)

  • Fixed: File inventories now include .module files and symlinked module directories by default. Previously pw_site_sync and related file commands silently skipped FormBuilder, LoginRegisterPro, WireSitemapXML, and any modules developed in symlinked sibling repositories.

1.7.0 (21 April 2026)

  • New: pw_site_compare tool for comparing local and remote sites across pages, schema, and files. Pages are matched by path, not ID, so comparison works across environments with different auto-increment sequences.
  • New: pw_site_sync tool for orchestrated deployment. Runs a comparison, optionally backs up the target, enables maintenance mode, pushes schema, pages (with file/image assets), and template/module files, then disables maintenance. Dry-run by default.
  • New: pw_maintenance tool for toggling maintenance mode on local, remote, or both sites. Front-end visitors see a styled 503 page; superusers and the PromptWire API are unaffected.
  • New: pw_backup tool for creating, listing, restoring, and deleting site backups. Database dumps use ProcessWire's built-in WireDatabaseBackup; file backups zip site/templates and site/modules.
  • Security: HTTPS is now enforced on the API endpoint. Requests over plain HTTP receive a 403 before the API key is checked. Local development environments can bypass this with PROMPTWIRE_ALLOW_HTTP in config-promptwire.php.
  • Security: Backup directories are automatically protected with a .htaccess that denies all web access. SQL dumps are never accessible via HTTP.
  • Changed: Module is now autoload so it can intercept front-end requests during maintenance mode. The overhead is a single file_exists() check per page load.

1.6.0 (21 April 2026)

  • New: pw_db_schema tool for inspecting database tables, columns, types, keys, and indexes.
  • New: pw_db_query tool for running read-only SELECT queries directly against the database. Mutations are blocked and a LIMIT is auto-injected.
  • New: pw_db_explain tool for running EXPLAIN on a query to diagnose slow queries and missing indexes.
  • New: pw_db_counts tool for a quick overview of row counts across core tables and the largest field data tables.
  • New: pw_logs tool for listing available log files and reading/filtering entries by level and text pattern.
  • New: pw_last_error tool for retrieving the most recent error from the error and exception logs.
  • New: pw_clear_cache tool for clearing caches by target: all, modules, templates, compiled, or wire-cache.

1.5.1 (21 April 2026)

  • Fixed: pw_page_push now auto-creates pages on the remote target when they don't exist yet, instead of failing with "Page not found".
  • Fixed: pw_page_publish no longer blocks publishing to a second target after a page has already been created on the first. Each target handles its own duplicate check independently.
  • Security: Users are now encouraged to rename the API endpoint file to a non-obvious name. The MCP server uses the full PW_REMOTE_URL as-is with no filename assumption.

1.5.0 (8 April 2026)

  • Changed: Module renamed from PW-MCP to PromptWire. Class names, file names, CLI scripts, API endpoints, and environment variables have all been updated.
  • Changed: Install directory is now site/modules/PromptWire/ (was PwMcp/).
  • Changed: On install or upgrade, the module automatically detects and removes old PwMcp/ and PwMcpAdmin/ directories.
  • Changed: Remote API file renamed to promptwire-api.php; config file to config-promptwire.php.
  • Changed: Environment variable PW_MCP_CLI_PATH renamed to PROMPTWIRE_CLI_PATH.
  • Changed: API key constant renamed from PW_MCP_API_KEY to PROMPTWIRE_API_KEY.
  • Kept: Data directories unchanged: .pw-sync/ for schema and site/assets/pw-mcp/ for content sync. No migration needed for existing data.
  • Fixed: Admin dashboard "Wire to File" exported pages to site/assets/promptwire/ instead of site/assets/pw-mcp/. One line in SyncManager.php was missed during the rename. Pull the latest from main for the fix. If any exports were created before updating, move them from site/assets/promptwire/ into site/assets/pw-mcp/ and delete the empty directory.

1.4.0 (8 April 2026)

  • Changed: Module restructured so the repo root is the module directory. Clone or download directly into site/modules/PwMcp/.
  • Changed: On install or upgrade, the module automatically detects and removes the old site/modules/PwMcpAdmin/ directory from pre-1.4.0 installs.
  • Fixed: schemaPush() routed to the remote API when both PW_PATH and PW_REMOTE_URL were set, so schema pushes silently went to production while reads used the local site. Now applies the same PW_PATH-first guard used elsewhere.
  • Fixed: validateRefs() defaulted to validating against the remote site when both env vars were set, inconsistent with the "local wins" rule. Now defaults to local when PW_PATH is present.
  • Fixed: pushPage() and publishPage() always returned success: true even when local or remote sub-operations failed. Failures were only visible in nested results. Top-level success now reflects actual outcome.
  • Fixed: publishPage() silently swallowed YAML parse errors and created remote pages with empty fields. Now reports the parse failure instead.
  • Improved: schemaPull() backs up existing fields.json and templates.json as .bak files before overwriting, so a mistaken pull is recoverable.
  • Improved: Remote API endpoint now sends X-Robots-Tag: noindex, nofollow header.

1.3.1 (27 March 2026)

  • Fixed: When both PW_PATH and PW_REMOTE_URL are set (hybrid config), runPwCommand now prefers the local PHP CLI. Previously PW_REMOTE_URL silently hijacked all commands, causing page queries to return stale remote data instead of live local data.
  • Fixed: Remote API endpoint now sends Cache-Control: no-store and Pragma: no-cache headers to prevent proxy or browser caching of API responses.

1.3.0 (27 March 2026)

  • New: pw_page_init tool for initialising or repairing page.meta.json for sync directories where content files were created manually.
  • Improved: pw_page_new is now idempotent. If the directory exists but page.meta.json is missing, it creates only the scaffold files without overwriting existing page.yaml or field files.
  • Improved: pw_page_publish auto-generates page.meta.json from page.yaml and directory structure when the meta file is missing.
  • Improved: Error messages in pw_page_push and pw_page_publish now show relative paths instead of absolute server paths, and include actionable hints.

1.2.0 (8 March 2026)

  • File sync, schema sync, cross-environment page ID resolution, remote API.

1.1.0 (5 February 2026)

  • Content sync (pull/push), page creation and publishing.

1.0.0 (29 January 2026)

  • Initial release. Site inspection, page queries, template/field introspection.

Last updated