Audit of the root CLAUDE.md (scored 76/100) found the architecture and
remote-ops coverage strong but the test workflow entirely undocumented and
several facts drifted from the tree.
Corrections (verified against the checkout):
- active_trip was japan-korea-2026; committed value is /trips/denmark-2026
and no japan-korea trip folder exists. Also note the value is a route.
- Admin2 2.0.10 -> 2.0.12 (installed version).
- demo-load/demo-reset described as italy-only; the Makefile loops over every
fixture trip under user/docs/demo/trips/.
- user/ gitignore claim omitted the three un-ignored site-owned plugins and
the secret/env exclusions.
Additions:
- Section 3 "Testing": make test/test-config/test-post/test-ui, the
auto-created testrunner account, Playwright layout, the auth.setup.js
storageState dependency, and GRAV_BASE_URL for worktree servers.
- Local dev command table, plus which theme assets are build outputs
(js/src -> bundles) versus hand-authored (css/style.css, css/tokens.css).
- Custom plugins: story-blocks and entry-actions alongside cache-on-save.
- Local plugin patches: install-plugins overwrites git-ignored third-party
plugins; deploy/patches/ + apply-plugin-patches is the tracked fix path.
- travel-memories service on 8082; make pixelfed-import.
Every make target and file path referenced was verified to resolve.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Close the remaining root-owned bind-mount vector: build-assets (a docker
run, missed by the docker-exec fix in 209b804) now runs as the host
uid/gid with HOME=/tmp for npm's cache. Verified: build completes clean,
zero root-owned files under user/themes, bundles byte-identical.
Solution doc updated from "still open" to fixed; CLAUDE.md stack section
now matches the Dockerfile's Grav 2.0.7.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0195b3cDdMeize2Mm1FgC2aU
Encode the dual-repo worktree SOP as make targets so no step is skipped:
worktree-new creates the outer worktree off main, inits its own user/
submodule, branches both repos, and starts an isolated Grav dev server on an
auto-picked free port (8090+) whose identity is persisted in a git-ignored
.worktree-env; worktree-rm tears it all down including the submodule deinit
that, when skipped by hand, leaves orphaned .worktrees/ dirs.
docker-compose.yml container_name + ports are parametrized as ${VAR:-default}
so the main checkout is byte-identical, and the 11 hardcoded intotheeast_grav
refs in local targets now use $(GRAV_CONTAINER). CLAUDE.md points at the
commands instead of the manual steps.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDS6t8wcpbwKvvrxykVQ5K
Code review flagged the shared partial's CLAUDE.md contract table as stale:
trip-feed-col.html.twig gained a trip_header_extras flag (set at :254, wired
from trip.html.twig) but the parameter table the trip/home callers rely on to
stay in sync had no row for it. Add the row + a note on what it gates and why
home omits it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDS6t8wcpbwKvvrxykVQ5K
The post form no longer hardcodes pageconfig.parent — cache-on-save derives the
write target from site.active_trip at submit time. Update the "Switching to a new
trip" section and the Trip-architecture note accordingly, and point at the Admin
Site → Active Trip page-picker. Drops the stale post-form.md / system.yaml sync.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Distills the 2026-07 Grav 2.0.4→2.0.7 cutover into a repeatable procedure:
the three-layer state model (plugin code / repo config / host env tree),
ordered per-phase make-target sequences, a smoke checklist that catches the
code-vs-config, stale-version, garbage-page, and git-sync-boomerang gotchas,
plus rollback and one-line invariants. Linked from CLAUDE.md Remote operations.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Np4cMQLF77i664CAQXySzU
Disproven end-to-end on this branch (Grav 2.0.4 + form 9.1.10): file-upload
returns 200, photo persists to disk, POST /post returns 200 with no error
page. The form plugin's upload path is byte-identical 9.1.6->9.1.10, so the
version was never the cause. The original failures were a test artifact --
upload fixtures named as dotfiles (.real-photo.jpg) are rejected by the form
as 'Bad filename'.
The note was also mis-scoped: a 'we're working on it, don't touch' reminder
from the upgrade session belonged in that session's commit/plan, not as a
standing project-wide directive that then told THIS rework branch to stand
down.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H1FrCYNq6RXdGYbn5PFrhM
Once user/env/<host>/ exists, Grav Admin saves ALL config (system +
plugin) into that env tree, not user/config/ — so prod's git-sync.yaml
lives at the env path, and Admin-on-server config edits are server-only
(not committed, not synced). Documented the footgun in CLAUDE.md §1
(session-loaded) and rewrote git-sync-notes.md: env-path location,
v3.4.4 folders format, gitignore table (incl. versions.yaml +
security-private.php TODO), and fresh-server enable procedure.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Np4cMQLF77i664CAQXySzU
Prod needs twig.cache:true / debug:false / auto_reload:false, but those
values break local dev, so they must not live in the committed
system.yaml. Add a per-environment override deployed only to the server
via Grav's environment://config (user/env/<host>/config/system.yaml):
- deploy/env/prod/system.yaml — version-controlled source of truth.
- make remote-apply-env-prod — writes it to the server + clears cache;
resolves the host in-recipe (WEB_HOST || REMOTE_HOST) to avoid the
recursive-make empty-export trap.
- remote-diag now shows the deployed override + whether twig cache is
populating, so prod-mode can be verified not assumed.
- CLAUDE.md §1 rewritten: never flip committed system.yaml; use the
override. Backlog updated (twig prod-mode + /post login-gate done;
note stale .env.prod GRAV_VERSION and pending git-sync).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Np4cMQLF77i664CAQXySzU
Update CLAUDE.md + architecture.md stack to Grav 2.0.4 stable, admin2 2.0.10,
gpm.releases: stable, and the three-category plugin-management model
(GPM-managed / custom-in-repo / remote-only git-sync). Add execution outcome,
Phase 3 prod fresh-install runbook (documentation-only), and mark plan Status
complete. Note the Form 9.1.10 filepond regression as a known issue owned by
the separate form-to-page rework.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Np4cMQLF77i664CAQXySzU
Add docs/solutions/architecture-patterns/dual-repo-submodule-workflow.md
covering the outer-repo + user/ submodule structure, when to bump the pin
(cross-repo feature boundaries, not routine content), the reachable/push-first
rules, and the worktree + per-worktree dev-server flow. Update CLAUDE.md's
folder explanation and add a "Dual-repo submodule structure" section.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Capture the safe procedure + three non-obvious traps from the standalone-
page cleanup: keep the folder as a routable:false data container, repoint
Back-link fallbacks to the grandparent (silent direct-landing regression),
and sync the gitignored demo source + Makefile or the next demo-load undoes it.
Seed CONCEPTS.md (Trip, Entry, Story, Active Trip) and surface docs/solutions/
+ CONCEPTS.md in CLAUDE.md so future sessions discover them.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Replace 'Shared feed-map partial' section with 'entry-map' partial + the
single MapUtils.initEntryMap map path
- Trip architecture: two content subfolders (dailies/stories as inert
routable:false containers); map/stats inline on trip page
- Fix stale references to deleted map/stats/dailies/stories templates in
architecture.md (template list, page tree, GPX flow) and trip-switching.md
(scaffold + verify steps)
- Correct GPX rendering: toGeoJSON bundled in map.js, no leaflet CDN
- Pre-launch smoke test now checks the trip page feed, not /dailies
Left docs/working/* (milestones, learnings, QA, plans) as point-in-time history.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Split env config into local vs remote:
- .env: local/shared config, always loaded (docker compose + make test)
- .env.test / .env.prod: full remote config, loaded on demand via ENV
Remote targets now generate -test/-prod variants (e.g. remote-install-prod);
a guard-env prerequisite blocks bare remote targets with no environment set.
Refresh .env.example to document the two-tier layout and add .env.prod/.env.test
to gitignore and the never-read list in CLAUDE.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a 'Shared trip-feed-col partial' section (callers, param table, the
home-predeparture sibling, and the initTripStats JS glue) and points the
trip-page filter-bar note at it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BftDn9vu9SonFAY4vxu4uk
Defines Status field values (Not started / In progress / Deferred /
Complete / Abandoned) and scanning rules so any session knows which
plans are open vs done without reading every file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
Replace stale linuxserver.io paths (abc:users, /app/www/public/*)
with current approach: run make fix-perms after plugin install or
container recreation.
Adds section 1 to CLAUDE.md covering the current development mode
config (twig.cache: false), the production mode values to restore at
launch, and an explicit rule never to flip modes mid-development to
work around bugs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>