# Journal Post Form — Review Handover & Owner QA **Date:** 2026-07-07 **Branch:** `feat/journal-post-form` (worktree `.worktrees/journal-post-form`) **State:** Implementation + code-review complete. **Remaining: owner UI QA (Part B) → then landing (Part A §Landing).** This doc has two audiences: - **Part A — Handover (Claude → future Claude):** exact branch state, what's committed where, the dual-session/worktree situation, and the landing procedure. Read this first in a fresh session before touching anything. - **Part B — QA checklist (Mischa):** the owner-session UI pass the test harness cannot do (it can't obtain your login). Run on http://localhost:8091. --- ## Part A — Handover (Claude → future Claude) ### What this branch delivers Front-end journal posting + editing, reusing `/post` + `add-page-by-form`: - Create/edit/delete/unpublish entries from the feed (plans `2026-07-04-journal-post-form`, `2026-07-04-frontend-entry-edit`). - In-form photo editor: add (HEIC→JPEG), inline-confirm delete, drag reorder, `photo-01..NN` renumber, first = cover (plan `2026-07-05-photo-editor-media-api`). ### Commits made in the 2026-07-07 review session (code-review F1–F8) All **local to this worktree's branch** — nothing pushed, no pin bump, no `content-push`. **Submodule `user/`** (on `feat/journal-post-form`): - `8db3ffe` — F1/F7: latch cache invalidation (`$cacheInvalidated`) to once-per-submit + info log — `plugins/cache-on-save/cache-on-save.php` - `7f6bf9e` — F4: `initDisclosure` reads each toggle's default from the rendered `[checked]` attribute instead of a `/\[published\]$/` field-name regex; rebuilt bundle — `themes/intotheeast/js/src/post-form.js` + `js/post/post-form.js` **Outer repo** (on `feat/journal-post-form`): - `d576487` — F2/F3/F6: shared `createPhotoEntry()` helper; register cleanup **before** the awaited success toast (fixes slow-success entry leak); AE3b disclosure-deviation test — `tests/ui/helpers.js` + 4 specs - `e10496a` — F8/F5: BUG-001 Part 2 solution doc + cross-link — `docs/solutions/integration-issues/grav-deleteall-doesnt-invalidate-page-tree-index.md`, `docs/working/bugs-and-fixes.md` Earlier same-branch commits (prior sessions): outer `d3c1779`, `f4dbac6`; submodule `7775a4e`, `a7bda6e` — create→edit stale-cache fix (`Cache::invalidateCache()`) + H1/M8 skip-with-reason. ### DO NOT commit — off-limits WIP left dirty on purpose - Submodule: `config/site.yaml` (owner's local `travelling:false` / `active_trip` testing config — `m` dirty is normal), `config/plugins/api.yaml`, `themes/intotheeast/js/src/post-form.css`, `themes/intotheeast/css-compiled/post-form.css` (the two CSS files get touched by `make build-assets` rebuilding from the in-progress `post-form.css` source — not part of this work). - Outer: the `user` gitlink (`M user` — pin **intentionally not bumped**). ### Dual-session / worktree situation (verified 2026-07-07) Two Claude sessions run in parallel. **Local isolation is real and proven:** - This worktree's `user/` git dir: `.git/worktrees/journal-post-form/modules/user`, branch `feat/journal-post-form` — its **own object store**. The other session's branch (`feat/trip-description-hero`) is not visible here and its HEAD commit does not exist in this object store. - Other checkouts: `content-fixes` worktree → `user/` on `feat/trip-description-hero`; main checkout → `user/` on `main`. **The only shared resource is Gitea `origin`** (the `intotheeast-com-content.git` content repo) + the single outer pin + outer `main`. Collisions can *only* happen at push / merge-to-main / pin-bump. **Therefore: never push, never `content-push`, never bump the pin from a worktree mid-flight. Landing is a single deliberate step the owner triggers.** ### Landing procedure (owner-triggered, once QA passes) — do NOT run unprompted 1. **Owner UI QA** (Part B) passes. 2. **Submodule first.** Reconcile `user/` `feat/journal-post-form` → `user/` `main` (merge; prefer the merge commit, not the branch tip). Push `user/` to Gitea → this triggers the production content pull via webhook. 3. **Bump the pin.** In the outer repo, stage the `user` gitlink pointing at that `user/` `main` merge commit (must already be pushed). Commit. 4. **Outer.** Merge outer `feat/journal-post-form` → outer `main`, push. 5. **Plugin patch.** `add-page-by-form` is GPM-managed/git-ignored; the Grav-2.0 header fix lives at `deploy/patches/add-page-by-form-grav2-header.patch`. Re-apply with `make apply-plugin-patches` after any plugin (re)install on the server — R9 (add photos on edit) breaks without it. 6. **Env override.** Re-run `make remote-apply-env-prod` after any fresh install (prod Twig cache settings live only in `user/env//`, not synced by content). 7. **Pre-launch smoke** (CLAUDE.md): submit one post via `/post` on prod, confirm it appears in the trip feed immediately (verifies cache-on-save under `twig.cache:true`). ### Running the tests - Full post suite: `GRAV_BASE_URL=http://localhost:8091 npx playwright test post/ --reporter=line` (20 pass as of 2026-07-07). - After any `js/src/*` edit: `make build-assets` (never hand-edit `js/post/*` or `css-compiled/*`). - `setup` project logs in → `tests/.auth/user.json`; specs run as the authenticated owner (anon-view clears storageState). ### Verified vs NOT verified - **Verified (harness):** 20 post specs on :8091 incl. ES1 (create→edit round-trip, the cache fix), AE3b (disclosure deviation), delete flow, anon/draft visibility, HEIC convert, photo renumber; `PhotoRenumberer` unit tests. - **NOT verifiable by harness (needs owner login / real device):** interactive photo add/delete/**drag** reorder in edit mode, on-device **touch**-drag, combined add+delete+reorder in one save. → **This is Part B.** --- ## Part B — Owner QA checklist (Mischa) Run logged in as the owner on **http://localhost:8091** (worktree dev server). Check each box; if any fails, stop and note it — do not land. ### Create - [ ] Post an entry with **1 photo** → success toast; entry appears in the active-trip feed **immediately**; that photo is the cover. - [ ] Post an entry with **multiple photos including a HEIC** → HEIC converts to JPEG, all attach, first image is the cover. - [ ] Post with **Published = No** (under "More options") → entry shows a **Draft badge** to you; open the same trip page in a **private/incognito window** → the draft is **absent**. ### Edit (open an entry's Edit link from the feed) - [ ] Change **title + body**, Save → feed reflects the new title/body. - [ ] Open the entry you *just* created for editing → **no "this entry no longer exists"** banner (the create→edit cache fix). - [ ] **Add** a new photo on edit → attaches and renumbers; regressions don't drop existing photos. - [ ] **Delete** a photo via the inline confirm → removed from disk; if you removed the first, the **cover updates** to the new first. - [ ] **Reorder** photos by **mouse drag** → order persists after Save; first = cover on the feed. - [ ] **Combined** in one save: add + delete + reorder → all three land correctly (cover=first, existing preserved, dropped removed). ### On-device - [ ] On a **phone or tablet**, edit an entry and **touch-drag** to reorder photos → works and persists. ### Delete - [ ] Delete an entry from the feed (Delete → Confirm) → card disappears and the folder leaves disk. - [ ] Delete → **Cancel** → nothing removed. When every box is checked, hand back to a fresh Claude session and point it at **Part A §Landing procedure**.