# PROGRESS

One entry per phase, appended as it completes. This is the file a future session reads to find out what actually exists, as opposed to what the specs say should exist.

Never delete an entry. If something was rebuilt, add a new entry saying so.

---

## Template, copy this per phase

### Phase NN: <name>
**Completed:** YYYY-MM-DD

**Built:** what actually exists now, in one short paragraph.

**Deviations from spec:** anything built differently from the docs, and why. If there are none, write "none". If a deviation was a real decision, it also needs a numbered entry in `07-DECISION-LOG.md`, and the number goes here.

**Known issues carried forward:** anything left broken or unfinished, and which phase will fix it. "None" is the answer you want.

**Acceptance criteria:** all passed, or list the ones that did not and why the phase was signed off anyway.

**Measurements:** any number worth keeping. Bundle sizes, Lighthouse scores, query counts, restore time.

---

## Phase 00: Bootstrap

**Completed:** 2026-09-10

**Built:** Local WordPress + WooCommerce via `wp-env` (Docker), the theme skeleton
(`wp-content/themes/brand-theme`, all placeholder `brand-theme` / `bc_` / `BC_`
naming per `CLAUDE.md` section 2) and the plugin skeleton
(`wp-content/plugins/brand-commerce`) exactly matching the file tree in
`docs/05-TECHNICAL-ARCHITECTURE.md` section 1. The plugin declares HPOS and
blocks-checkout compatibility on `before_woocommerce_init`, bails with an
admin notice when WooCommerce is inactive, and autoloads `BC_*` classes from
`includes/**/class-*.php`. `bc_asset()` reads the content-hashed build
manifest with a `filemtime()` fallback. Build pipeline (`sass`, `esbuild`,
`tools/hash-assets.js`, `tools/check-budget.js`) and lint pipeline
(`composer.json`, `phpcs.xml`) both wired and passing. `deploy/.cpanel.yml`
copies only the two tracked directories on deploy. Git initialised with one
clean initial commit of docs and config.

**Deviations from spec:**
1. `npx wp-env start` itself (the `@wordpress/env` Node CLI) reliably exits
   with code 0 right after the `mysql` container starts, without building
   the `wordpress` image, running the WordPress install, or extracting the
   WooCommerce zip. Root cause not identified; the underlying `docker
   compose` commands work correctly on their own. Worked around by driving
   `docker compose` directly against the generated compose file. Documented
   in full in `deploy/deploy-notes.md`, "Known issue on this machine:
   `wp-env start` exits early". This does not affect the site's runtime
   behaviour, only how the local container has to be brought up on this
   machine.
2. The WooCommerce plugin's local folder name is `woocommerce.latest-stable`
   (wp-env names zip-sourced plugins after the source basename), not
   `woocommerce`. Functionally identical, our own guard checks
   `class_exists( WooCommerce::class )`, not the folder path. `wp plugin
   activate woocommerce.latest-stable` on this machine; production installs
   WooCommerce normally through the WordPress.org plugin directory, where it
   will be named `woocommerce` as usual.
3. `wp-env`'s `.wp-env.json` has no field for a non-default database table
   prefix, and the official WordPress Docker image only reads one from a
   `WORDPRESS_TABLE_PREFIX` environment variable. That variable was added by
   hand to the machine-local generated `docker-compose.yml` (not part of this
   repo), so it does not persist across `wp-env destroy`. Documented in
   `deploy/deploy-notes.md`. Does not apply to the real hosting install,
   where the prefix is set once in the installer form.

**Known issues carried forward:** None for this phase's own scope. The
staging subdomain (item 12) was not provisioned, it needs the Namecheap
cPanel login, which this session does not have. Steps are written out in
`deploy/deploy-notes.md` under "Staging subdomain: NOT YET PROVISIONED" for
whoever has that access to run.

**Acceptance criteria:**
- [x] Local WordPress site brought up with WooCommerce active (via the
      docker-compose workaround above, `wp-env start` itself is broken on
      this machine)
- [x] Theme activates, homepage returns HTTP 200, no PHP fatal/warning/notice
      in the response body
- [x] Plugin activates without a fatal; deactivating WooCommerce leaves
      `brand-commerce` active with no fatal (the admin-notice code path was
      not visually screenshotted in wp-admin, verify this once looking at
      the site)
- [x] WooCommerce Settings, Advanced, Features: HPOS is available; turned on
      via `FeaturesController::change_feature_enable()` since it is off by
      default on a fresh install; `brand-commerce` is listed under
      "compatible", zero plugins under "incompatible"
- [x] `npm run build` produces hashed files and a valid `asset-manifest.json`
- [x] `npm run size` passes
- [x] `composer run lint` passes on both directories, 19 files, zero errors,
      zero warnings
- [x] Table prefix is `unxx_`, not `wp_`, verified with `SHOW TABLES` against
      the database
- [ ] Staging subdomain: not provisioned, needs Namecheap cPanel access, see
      "Known issues carried forward"
- [x] `docs/PROGRESS.md` has this entry
- [x] `git log` shows one clean initial commit

**Measurements:**
- Table prefix: `unxx_`
- Staging URL: not yet provisioned
- CSS bundle: main.68b329da.css, 1 byte (main.scss is still empty, no styles written yet)
- JS bundle: main.ee4a59b5.js, 12 bytes (main.js is still empty, no code written yet)

---

## Reference numbers to fill in as they are measured

| Measurement | Target | Phase | Actual |
|---|---|---|---|
| CSS bundle, minified | under 45 KB | 03 | |
| JS bundle, minified | under 25 KB | 03 | |
| Homepage LCP, throttled 4G | under 2.5s | 13 | |
| Homepage CLS | under 0.05 | 13 | |
| Homepage total transfer | under 900 KB | 13 | |
| Product page LCP | under 2.5s | 13 | |
| Product page total transfer | under 800 KB | 13 | |
| Autoloaded options | under 800 KB | 13 | |
| Queries, heaviest template | under 60 | 13 | |
| Order list, 500 orders | under 3s | 09 | |
| Dashboard, 5,000 orders | under 1.5s | 10 | |
| Backup restore, wall clock | under 60 min | 14 | |
| Contrast re-check after brand palette | all AA | 03 | |
