Three environments and how they work together
Environment A — AI development workspace
The assistant modifies a checked-in HSLG source snapshot, generates WordPress ZIPs and documentation, executes available local tests, and may compile Android artifacts only when its own Android SDK, npm and Maven dependencies are complete. The workspace can reset between chats. File downloads alone do not preserve local environment state across future sessions. A release archive, lockfile and toolchain checksums are the durable handover.
The assistant cannot SSH into hq.hslg.uk without an explicitly connected and authorised tool. It cannot infer real MariaDB migration success from local PHP test doubles. APK compilation, signing, verification and device QA must be reported separately. Generated keystores and credentials must never be bundled with public source.
Environment B — private Ubuntu build workspace
The operator's internet-connected Ubuntu/Virtualmin machine contains private HSLG build tools under /home/media/.hslg-build: Node 22.23.3, pnpm 10.15.0, Temurin Java 21, Android SDK Platform 36, Build Tools 36.0.0, Platform Tools and GitHub CLI as previously installed and reported. GitHub CLI installation does not imply GitHub use; this project does not require GitHub. The Gradle project uses its pinned wrapper; system-wide Gradle installation is unnecessary. This workspace can resolve missing dependencies on demand but should not be the routine place the operator must build releases.
The separate private Composer executable is /home/media/.local/bin/composer, with configuration/cache under /home/media/.config/composer and /home/media/.cache/composer. PHP Composer dependencies should be installed from an audited composer.lock in a private vendor directory, not downloaded ad hoc into shared system paths. The current HSLG App API ZIP does not include a Composer dependency closure.
Environment C — Virtualmin-managed website
/home/media/public_html/ is the WordPress document root for https://media.hslg.uk/. The browser-visible presentation plugin and the independent HSLG API plugin run here. MariaDB supplies current content/API storage. Source files, toolchains, developer archives, signing keys, caches, or raw build logs must not be left under public_html.
WP-CLI commands should run as the site owner media with --path=/home/media/public_html/. This avoids root-created files. Only WordPress's documented post APIs should create/edit documentation pages. No direct SQL updates to wp_posts or revision tables are permitted.
Handoffs
1. Record the source archive name and checksum. Review any native dependency versions/locks.
2. Build/test WordPress presenter and API independently from the same reviewed source checkpoint.
3. Build the Capacitor Android package in the AI workspace only if dependencies exist there. If not, report the blocker and arrange a portable offline cache. Never label a standalone WebView APK as Capacitor.
4. Deliver presenter ZIP, API ZIP when changed, native binary when proven, source ZIP, documentation bundle, development log and gate evidence as distinct artifacts.
5. Back up the HSLG WordPress database and plugin directories before applying updates to media.hslg.uk.
6. Install the updated HSLG documentation publisher ZIP in WordPress. Its activation or updated bundle automatically creates and revises owned pages; verify WordPress revisions and review any blocked-publication admin notice.
7. Test customer flows on the staging domain/device and record actual results. Return a failure report to the AI workspace for the next code change.
Download and failure management
Android command-line tools, platform files, Gradle and Capacitor npm tarballs were exchanged as downloadable archives because the AI build container lacked repository access. The user uploaded packages to the ChatGPT project Library. Each supplied file must have a precise version, filename, direct origin URL and checksum in the dependency ledger. Uploaded top-level npm packages are not a complete transitive dependency tree; a successful APK build still requires all nested packages and Gradle/Maven artifacts.
A build runner must fail when package resolution fails. A partial APK preview must not be presented as a real Capacitor release. Build logs should show source commit/archive fingerprint, lockfile, tool versions, native SDK versions and signature. If the assistant's execution environment resets, recover from the source archive plus the pinned build kit rather than depending on the previous local filesystem.
Security and permissions
Use media ownership for site-local tools and artifacts. Keep build caches outside public_html. Never run unreviewed curl | bash commands as root. Verify downloaded packages against publisher checksums when available, restrict signing keys to private storage and test backups/restores independently. Use HTTPS and scoped privileges for all deployment operations.
Costs and workload
The existing Virtualmin host reduces monthly fixed infrastructure expense, but consumes disk/CPU for builds and backups. AI workspace reuse reduces repeated setup work but cannot be assumed persistent. Separate CI/macOS resources for IPA compilation may incur fees. A single operator should prioritise reproducible scripts, backups and automated gates over a complex multi-server deployment platform.
Three environments, three different forms of evidence
The AI development environment is an isolated workspace used to read HSLG source, edit files, run available tests and package downloadable artifacts. Its filesystem and caches may be temporary. Its network may not reach npm, Google Maven or arbitrary package repositories. A generated ZIP must contain the complete checked-in project and metadata, because the next assistant session may not retain the old workspace. An AI statement that a file exists must be supported by an actual exported artifact.
The private Ubuntu build environment belongs to the media Virtualmin user. Its designated directory is /home/media/.hslg-build, outside the site's document root. It can hold pinned Node, pnpm, Java, Gradle, Android SDK, tool caches, extracted source for builds and logs. This machine has network connectivity and can resolve dependencies that the AI environment cannot. This environment is not a public website and should not be backed up by treating it as editorial content.
The live/staging website environment is the media.hslg.uk WordPress installation at /home/media/public_html/, managed by Ubuntu, Webmin and Virtualmin with MariaDB and domain-specific PHP-FPM. It serves customers and administrative editors. WordPress plugin updates and migrations belong here; native compilation, random downloads, signing material and large dependency caches do not. No release step may globally reconfigure Webmin or Virtualmin just to fix an HSLG dependency problem.
The Android testing environment is a separate real phone. It can prove OS permissions, camera scanning, keyboard layout, app-link routing, haptics, network transitions and installation/signature behaviour. Browser automation cannot supply this evidence. An iOS release requires a further macOS/Xcode environment that has not been proven available for this project. Do not silently treat Android acceptance as iOS acceptance.
Reconstructing the AI workspace from nothing
Start from the latest complete source archive and the verified artifact manifest, not an unexplained working directory. Extract it into a new private workspace. Inspect the root README.md, AGENTS.md, per-directory agent guides, changelog, TODO, history boundary and dependency policy before changing files. Run source/governance checks before modifications, and retain the original outputs as baseline evidence. Where tests require unavailable packages, record a blocked result rather than skipping them without comment.
Dependencies uploaded via chat must be identified by exact name, version, origin URL, local filename and SHA-256. Installing Gradle itself, for example, does not populate Google Maven dependencies required by Android builds. An npm .tgz for a top-level Capacitor plugin does not contain all its transitive imports. Do not claim a native build can run offline without a complete lockfile and resolved package/cache inventory. The direct package list is a provenance ledger, not a proof of a full resolved dependency graph.
Produce a changed source archive, plugin ZIPs and run report only after the appropriate gates. Keep output checksums with each file; scripts should not require retrieval from a path that existed only in a previous AI session. Generated images, provider secrets and signing keys have different storage and licensing rules from regular source files. Do not commit secrets to documents or present them as downloadable example configuration.
Inspecting the Ubuntu and Virtualmin state before doing anything
Connect to the existing host using the authorized system account. Determine Ubuntu version, CPU architecture, disk space, PHP versions, selected site's PHP-FPM handler, MariaDB version, Node, Java, Android SDK, WordPress root and file ownership. The disaster-recovery command scripts under docs/disaster-recovery/commands/ include read-only inspection helpers; inspect their contents before running. Do not infer the correct FPM pool filename from a previous screenshot, because Virtualmin may number pool files differently after reinstallation.
Confirm the intended virtual server and Unix user. The media account's public website is /home/media/public_html/; the private build root is /home/media/.hslg-build. Keep the directory tree owned by the appropriate site account and restrictive enough that other hosted users cannot read private caches or signing material. Test access to the build root as the virtual user and confirm it is not served by HTTPS. Avoid recursive ownership or permission commands aimed at /home, /var/www, /etc or all Virtualmin websites.
When PHP upload limits need changing, first compare PHP CLI, web SAPI, the active PHP-FPM pool and per-domain overrides. The reported past staging workaround used upload_max_filesize=64M and post_max_size=80M, but those are historical values, not a universal recommendation. Only apply these values when needed, after recording the original configuration and proving the change is local to media.hslg.uk. Run PHP-FPM configuration validation, verify reload effects and test an actual WordPress upload. A successful php -i call may describe the CLI configuration rather than the site's FPM worker.
Native build toolchain and its failure boundaries
The project is based on Node 22.x, pnpm 10.15.0, Java 21, Gradle 8.14.3 and Android SDK platform/build tools 36 in the recorded 2026 checkpoint. Treat them as pinned historical inputs to verify against the project and lockfile; do not automatically replace them with the newest versions during recovery. Gradle, the Android Gradle Plugin and the Capacitor packages have distinct version identifiers and dependency graphs. Preserve exact versions in the source manifest and source-controlled build files.
A correct native build first installs and verifies the resolved JavaScript dependency graph. It builds the web assets with the native entry point, syncs through Capacitor, runs Android Gradle with the appropriate SDK and plugins, and exports a signed APK. zipinfo, APK signing verification and native dependency listing should be included in the release evidence. A valid JAR file on disk is not evidence that the Gradle build can resolve its nested Maven coordinates. A signed WebView preview without Capacitor plugins must not be accepted as the requested app.
Keep Android test signing identities and release signing identities distinct. Restore an existing key only from a secure supported backup; a newly generated signing key cannot update an APK signed with a lost different private key. Treat any key or password in chat as potentially exposed and rotate accordingly. For iOS, restore the necessary certificates/profiles and validate Apple's currently applicable distribution requirements on macOS; there is no iOS compile path on Ubuntu alone.
Transferring work between environments
The direction of source promotion is AI-reviewed project source to private build/staging environment, then actual runtime evidence back to the development history. A browser-visible WordPress page is not the canonical source repository. User-approved plugin ZIPs are installed through WordPress; WordPress creates or revises only plugin-owned documentation pages. SQL migration evidence and rollback notes must be captured before a database-affecting API plugin update.
The browser presenter is useful for reviewing copy, images, navigation, tablet/table numbers and negative UX states. It uses demonstrative adapters. The Android phone is the target for confirming actual camera permission, QR decoding, app-link verification, haptics, service retries, login sessions and native persistence. Keep observations separated by environment in test reports. Do not promote browser-only success to a native acceptance badge.
The AI environment should not run a privileged command on Virtualmin as a workaround for build tooling. The owner specifically does not want to administer documentation publication by root SSH or WP-CLI. Automatic documentation is a property of the documentation publisher plugin's activation/release lifecycle. SSH scripts remain diagnostic and disaster-recovery references, not routine documentation-update instructions.
Release failure and rollback workflows
If generation fails in the AI workspace, preserve the last good source ZIP and release report and correct the source before exporting. If an Ubuntu native build fails, preserve the exact terminal output, toolchain versions and dependency state without cleaning the entire server. If WordPress publication fails because an existing page was manually edited or its path is owned by another plugin, leave existing content intact and surface the blocking page for review. Do not delete or recreate pages to force the release through.
If the API update fails after a migration, determine whether the schema is additive and whether rollback is possible without data loss. A plugin downgrade does not necessarily downgrade a database schema. Restore a backup only after evaluating records created after that backup. If the entire server and all backups are destroyed, customer records, page revisions, credentials, original signing keys and payment evidence cannot be reconstructed from source code. The disaster-recovery manual distinguishes infrastructure rebuild from actual data restoration.
Cost and evidence accounting
Keep reusable downloads and caches where they avoid unnecessary network work, but do not make the system depend on a cache that is absent from the recovery plan. Measure disk use, patch/security overhead and backup cost. Retire unsupported packages deliberately and test replacements; a cached package is not guaranteed to remain acceptable for commercial distribution. A single operator benefits most when an environment can be rebuilt by following documented steps and comparing expected output, not by memorizing a series of ad-hoc fixes.
Each release record should identify what ran where: AI static checks, Ubuntu dependency install/build, WordPress staging plugin update, MariaDB migration, and Android physical-device review. Missing evidence remains missing; it is not converted to a passing result by the presence of scripts, compilation logs from a different source version, or a newer documentation page.