Changelog

What changed in each release of PromptWire.

1.13.0 (14 Aug 2026)

  • Fixed: Options fields now resolve by label across environments. When a page is pushed between environments (e.g. local → production), options field IDs are matched by title rather than raw integer. Option IDs are auto-incremented per install and routinely differ between sites; matching by label means the correct option is always selected regardless of which environment generated the YAML. Applies to both the local PHP push path and the remote API.
  • Fixed: FieldtypeFile and FieldtypeImage fields now register disk-resident files during pw_page_push. Previously, a file placed in the page's asset directory via pw_page_assets, pw_file_sync, or a manual copy was silently skipped when pushing field metadata — the file existed on disk but was not registered in ProcessWire's Pagefiles collection. The push now detects this and adds the Pagefile object before writing the description, so a single pw_page_push is enough to register and describe a newly-uploaded file.
  • Fixed: pw_page_init no longer requires manual deletion of page.meta.json when the file was written by a remote pull. A remote pull sets pageId to the remote environment's integer; this caused initPageMeta to treat the page as already locally-linked and block re-init. The guard now checks ids.local exclusively — a meta with only ids.remote is correctly treated as unlinked locally and proceeds without the manual delete step.
  • New: pw_page_init gains dry-run mode. Dry-run by default — preview what would be linked or scaffolded without writing page.meta.json. Pass dryRun: false to apply. Consistent with every other write tool in the suite.
  • Improvement: pw_page_init preserves ids.remote across re-init. Any existing remote-environment tracking in the old meta is carried forward into the new one.
  • Migration impact: zero. All changes are backwards-compatible. Existing page.yaml files with integer option IDs are resolved by label on the next push; no YAML edits required.

1.12.7 (27 Jul 2026)

  • Fixed: pw_page_publish on remote now tries page:update first and only falls through to page:create when the page is not found. Previously, an interrupted publish could leave an orphan on production with a -1 slug suffix. The remote branch now mirrors the same try-update-then-create pattern used by pw_page_push.
  • Migration impact: zero. Fixes duplicate orphan pages visible in pw_site_sync dry-runs.

1.12.6 (14 Jul 2026)

  • Fixed: MCP remote client no longer misreports page:update 404s as "Remote API not found". Application errors such as Page not found: /path/ are surfaced verbatim, restoring the page:create fallback when pushing a locally-created page to production for the first time.
  • Fixed: HTTP 400 application errors (for example Template not found: guide-page or Parent page not found: /guides/) are returned verbatim instead of the opaque Remote API returned HTTP 400.
  • New: clear-cache procache target (included in clear-cache all when ProCache is installed). Clears ProCache static cache and reports how many entries were removed.
  • Migration impact: zero.

1.12.5 (14 Jul 2026)

  • New: pw_page_rename tool (+ page:rename CLI command). Renames a ProcessWire page slug on local, remote, or both. Dry-run by default. Checks for name collisions and refuses system pages (home, admin). Reports whether PagePathHistory is installed (auto-301 from old URL). See Page Slug Rename.
  • New: Local sync folder reconcile after rename. When a local rename succeeds, PromptWire automatically moves site/assets/pw-mcp/.../old-slug/ to the new path and updates page.meta.json. Pass reconcileLocal: false (MCP) or --no-reconcile (CLI) to skip.
  • Remote routing: targets: remote and targets: both call the remote PromptWire API — no SSH or admin clicks required. Same pattern as pw_page_push.
  • Migration impact: zero.

1.12.4 (14 Jul 2026)

  • Fixed: yamlValue() now correctly quotes non-string objects after a (string) cast. Fields backed by custom ProcessWire field types that return an object rather than a plain PHP string (for example SeoNeo) previously bypassed colon/special-character quoting, causing js-yaml to throw bad indentation of a mapping entry on the next remote push when a value contained a colon (for example title: Foo: Bar must be title: "Foo: Bar").
  • Migration impact: zero.

1.12.3 (14 Jul 2026)

  • Fixed: PHP CLI page:push now rejects --targets=remote and --targets=both with a clear error. Previously the CLI silently pushed to the local database only — remote push is an MCP server concern. The error points to pw_page_push with targets="remote" as the correct tool.
  • Fixed: Nested per-target push errors now surface at the top level. When pw_page_push targets="remote" fails, the concrete error (for example a YAML parse failure) is included in the top-level error string instead of being buried in data.results.remote.error.
  • Improved: YAML parse errors in parsePageYaml now include an actionable hint when an unquoted colon in a field value is the likely cause.
  • Migration impact: zero.

1.12.2 (25 May 2026)

  • New: NEW* placeholder support in repeater and matrix fields. When a repeater/matrix item in page.yaml has _itemId: NEW1 (or NEW2, etc.), PromptWire creates a fresh item instead of skipping it as missing. For matrix fields, the optional _matrixType key sets the matrix type automatically. See Content Sync — Matrix placeholders.
  • Impact: The manual matrix:add → page:pull bootstrapping step for new pages goes away. A single page:publish → page:push pass now creates and populates matrix items in one shot.
  • Migration impact: zero. Existing page.yaml files with integer _itemId values continue to work exactly as before.

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