Five weeks of undocumented evolution left the docs describing a site that
partly no longer exists, with nothing marking which documents were historical.
The code is treated as the source of truth throughout; every claim below was
verified against code, config or the Makefile rather than inferred.
Two mechanisms, following patterns the repo already used:
- docs/reference/superseded-decisions.md (new) — one authoritative table of all
14 reversals: what was planned, where, what is true now, when, and why. Plus
a short list of decisions that were NOT reversed, since their planning docs
are old enough to look suspect.
- Inline "> **Superseded ...**" notes at each stale claim, so a claim can never
be read un-corrected. This mirrors the existing "> History:" notes in
architecture.md and "> **Changed 2026-07:**" in trip-switching.md.
Scope split by tense: present-tense docs (CLAUDE.md, reference/, guides/,
README.md, CONCEPTS.md) are corrected; past-tense records (plans/, specs/,
milestones/, summary.md, pm-analysis.md) are annotated only, never rewritten —
their staleness is what makes them records.
Present-tense corrections:
- CLAUDE.md asserted css-compiled/ is generated from css/style.css and
css/tokens.css. That source relationship does not exist: css/ is hand-authored
and served directly via assets.addCss in partials/base.html.twig, while
css-compiled/ is esbuild output from the CSS imports inside js/src/*.js.
Highest-severity finding — an always-loaded file inviting a hand-edit of a
generated bundle.
- README.md documented every remote-* target without the -test/-prod suffix
guard-env requires, so its entire server runbook was unrunnable, and listed
7 of ~20 targets while CLAUDE.md designates it authoritative for the full
list. Rewritten with all targets, grouped, and the suffix rule stated.
- README.md told readers to "git clone" into user/, which is a submodule.
- architecture.md: nav is Home + Trips + (authenticated) New Post, not
"Home + Past Trips only"; template tree omitted trips.html.twig,
post-form.html.twig and forms/, and placed base.html.twig at templates/ root
rather than in partials/; entry-actions has three API routes, not just delete;
added the undocumented css-compiled/maplibre-gl.css output and a section on
the /post pin editor as the one sanctioned non-entry-map map.
- design-system.md: documented 13 colour tokens against 19 in tokens.css
(missing --color-error, --color-draft-accent and four glass overlays); claimed
"all 3 map templates"; and described --color-canvas as "white".
- design-system-light.md documented a light palette in present tense. No light
mode exists — tokens.css has a single :root block, no prefers-color-scheme or
data-theme switch, and no light hex appears in css/. Banner added.
- posting.md said photos were optional; they are required, 1-6. It documented
hero_image, which was removed for entries (stories keep it). It had no mention
of the frontend edit flow or photo editor, both shipped 2026-07-08. Photo
files are photo-01..NN, zero-padded.
- working/README.md advertised summary.md as the project's "current state" while
summary.md describes Leaflet, /tracker, /map and /stats. Most misleading line
in the tree.
- CLAUDE.md: recorded js/src/location-map.js as the one sanctioned exception to
the single-map-path rule, and documented that make start/setup fail on a clean
checkout because docker-compose.yml still builds a travel-memories service
whose source moved out in a80b0a9.
Also: 2026-07-23-post-form-location-override.md read "Not started" while merged
in user/ as dd19995; status corrected.
Findings that are not documentation problems — the compose breakage, a
repeatable drift check, the unused shortcode-gallery-plusplus, and demo fixtures
for retired views — are collected in
docs/working/2026-07-25-doc-drift-recommendations.md and deliberately not acted
on. Design and verification method: docs/working/specs/2026-07-25-docs-reconciliation-design.md
The submodule gitlink is deliberately not bumped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
7.7 KiB
Recommendations from the 2026-07-25 documentation reconciliation
Status: 📋 Proposed — nothing here has been acted on. Decide per item.
The reconciliation pass (see specs/2026-07-25-docs-reconciliation-design.md)
corrected the documentation. It also surfaced problems that are not documentation problems, plus
process changes that would stop this drift recurring. Those are collected here rather than mixed into
a docs diff.
Ordered by what I would do first.
P1 — make start and make setup are broken on any clean checkout
What. docker-compose.yml still declares a travel-memories service with
build: ./services/travel-memories. That source was removed in a80b0a9 ("moved to separate
project") and services/ is gitignored, so the build context does not exist. make start is
docker compose up -d (all services), and make setup calls it.
Proof.
$ docker compose build travel-memories
unable to prepare context: path ".../services/travel-memories" not found
Why it has stayed hidden. A machine that built the image before a80b0a9 still has
travel-blog-intotheeast-travel-memories:latest cached, so docker compose up -d reuses it and never
rebuilds. It breaks for a fresh clone, for every new worktree (different COMPOSE_PROJECT_NAME →
different image name → forced rebuild), and on the main checkout after any docker image prune. This
is why make worktree-new calls start-grav, not start.
Options.
- Delete the service from
docker-compose.yml(recommended). It lives in another project now. If that project needs to run alongside Grav, it can carry its own compose file. - Move it into a compose profile (
profiles: [tools]) sodocker compose up -dskips it by default. - Keep it and point
buildat the new location — only if you actually want the two coupled again.
Until this is decided, CLAUDE.md and README.md now warn to use make start-grav. That is a
signpost around a bug, not a fix.
P2 — A repeatable drift check
Deliberately out of scope for the one-time pass; this is the item that stops the whole problem recurring. Every defect found was mechanically checkable — a route, a path, a token name, a make target, a field rule.
Proposal. A make docs-check target that fails loudly when the present-tense docs assert
something the code contradicts:
- Grep
CLAUDE.md,docs/reference/,docs/guides/,README.md,CONCEPTS.mdfor references to retired routes (/map,/stats,/tracker,/dailies,/stories) and dead tech (Leaflet). These are already forbidden byCLAUDE.md, so any hit is a defect. - Assert every
templates/*.html.twigandtemplates/partials/*.html.twignamed inarchitecture.mdexists, and flag templates that exist but are undocumented. Both directions of drift were present this pass. - Diff the
--color-*token names indesign-system.mdagainstcss/tokens.css. Six were missing. - Assert every
make <target>mentioned inREADME.mdis a real target, and that no bareremote-*target is documented without an env suffix. This alone would have caught P4. - Assert file paths cited in
CLAUDE.mdexist. A prior pass shipped a path tojs/src/maplibre-utils.js, which never existed.
Deliberately excluded: docs/working/. Those documents are records and are supposed to drift;
scanning them would produce permanent noise.
Sequence this after P1 — otherwise the first thing the check reports is P1.
P3 — Plan status can silently lag a merge
plans/2026-07-23-post-form-location-override.md read 📋 Not started while the feature was merged
in user/ as dd19995. Nothing connects a plan's status line to the commit that lands it, so the
convention depends entirely on remembering.
Options.
- Add the plan path to the feature's commit or PR body, so
git log --grepcan find plans whose work landed but whose status never moved. Cheapest, no tooling. - Extend the P2 check: for each plan not
✅ Complete/❌ Abandoned, look for a merged branch whose name matches the plan slug and warn. Catches it automatically; some false positives. - Accept it and rely on the convention. Reasonable — this was one miss across 41 plans.
P4 — README.md was designated authoritative for a list it did not hold
CLAUDE.md's entry-point table sends readers to README.md for "the full make command list".
Before this pass, README documented 7 of ~20 remote-* targets, and documented all of them without
the -test/-prod suffix that guard-env requires — so its server runbook was not executable.
Corrected now, but the structural point stands: a doc promoted to "the authoritative list of X"
acquires a completeness obligation it did not have as prose. The Makefile is the real source of
truth. Consider either generating the command tables from Makefile comments, or softening the
CLAUDE.md pointer to "common commands" and letting make help be authoritative.
Related: docs/guides/deploy-cycle.md had the env-suffix rule right the whole time. The defect was
README duplicating the same knowledge and drifting. Fewer copies would have prevented it.
P5 — shortcode-gallery-plusplus is installed with no consumer
plugins.txt lists it, but there is no [gallery] shortcode anywhere in templates/ or pages/.
Entry galleries are PhotoSwipe, wired in js/src/main.js against .pswp-gallery markup from
partials/entry-journal.html.twig.
Careful before removing it. plugins.txt does not list shortcode-core, which is present as
a GPM dependency — and story-blocks needs shortcode-core. Dropping
shortcode-gallery-plusplus could take shortcode-core with it and break stories.
Recommendation. Add shortcode-core to plugins.txt as an explicit, first-class dependency
first, then remove shortcode-gallery-plusplus and verify a story page still renders. Do not do
these in one step.
P6 — Demo fixtures still contain retired views
user/docs/demo/trips/italy-2025/ ships map.md, stats.md and stories.md — pages for views
retired on 2026-07-04. The newer italy-2026-demo fixture has no map.md/stats.md, so the fixtures
disagree with each other.
Low impact (demo trips are gitignored in the pages tree and loaded on demand), but make demo-load
copies them in, so a demo trip can materialise pages for views that no longer exist. Delete
map.md and stats.md from italy-2025; keep stories.md only if the container is still needed.
This is a user/ submodule change, which is why it was left out of this pass.
P7 — Structural notes worth a decision
design-system-light.md is a record, not a reference. It documents an unimplemented palette and
now carries a banner saying so, but it still sits in reference/ — the "stable facts" tier. Moving it
to docs/working/ would make its status structural rather than dependent on a reader seeing the
banner. Counter-argument: it is the natural starting point if a light theme is ever built, and
reference/ is where someone would look. Either is defensible; the banner makes it safe for now.
milestone2-template-refactor-brief.md sits loose in docs/working/ while the milestone docs live
in working/milestones/. Cosmetic, but it is the kind of thing that makes a folder stop being
self-explanatory.
The summary.md lesson generalises. The single most misleading line in the tree was
working/README.md advertising summary.md as "current state". A stale document is survivable; an
index that points at a stale document as authoritative is not, because it defeats the reader's
judgement. Worth remembering the next time an index gets written: describing a document's role is
itself a factual claim that can rot.