Every DELIBERATE difference between this repo and dash-documentation-boilerplate, with its reason. This file is the boundary between design and drift:
- Template syncs read this file FIRST and must not "restore" anything recorded here.
- A difference not recorded here is treated as drift and will be synced away.
- Record the divergence in the SAME commit that creates it — one line: what differs, why, and what the template would otherwise do.
- An empty list is a statement too: it means this repo intends to match the template exactly.
Fleet precedents for what belongs here: flexlayout's own-source
_build_llms_doc dedup and app-key sourcing; flows' own
_health_body payload shape (ports the healthz CONTRACT, not the
template's file); clerkhook's minimal {ok, app, build} healthz and
its heartbeat-as-before_request (the single anonymous 200 on a locked
host); muischeduler's no-npm dependabot scope.
What this file is NOT. Every fork re-keys its identity — app key,
BASE_URL, brand strings, the SATELLITE_APP_KEY fallback literal,
its own doc set. That is the fork ritual, not a divergence, and it is
not listed below. Nor is drift: places where this repo is simply
BEHIND the template are listed in the last section, so a sync knows
to close them rather than treat the gap as a decision.
Guard entries. Every line here documents something this repo MATCHES or deliberately does NOT carry — an absence a sync would otherwise read as drift and helpfully undo. Nothing in a diff distinguishes a deliberate absence from an accident, and a test docstring is invisible to both the fan-out and the next sync author, who read THIS FILE. Adding one costs a sentence; the alternative costs a fortnight of a defect walking back in.
- There is no User-Agent list in this app, and there must not be
(1.6.34).
dash_improve_my_llms.classify()is the one classifier. This tracker carried a local list for a year: it filed ClaudeBot — Anthropic's TRAINING crawler — as search, still named the retiredanthropic-ai/claude-webtokens, and counted every UA-less or library client as a person. Every host in the fleet reported those numbers. A token the registry lacks is a pushback to the package seat, never a table here.tests/test_analytics_classifier.pygreps the module and goes red if one returns. The same rule now coversvendor_class(1.6.44 item 8): prefer the package's value, derive from the package's REGISTRY when absent, never from a local map. - Content images carry width/height and NEVER
loading/decoding(1.6.44 item 6f). Neither is a prop of dash 4.4.1'shtml.Imgand Dash RAISES on an unknown one, so adding them is a collection error on every page with an image rather than a degraded hint.tests/test_a11y_agentic.pypins the TypeError and goes red the day Dash learns the props — at which point the sub-item can be completed instead of capped. - The image size readers use the STDLIB only (1.6.44 item 6f).
Pillow is installed here by two BUILD-TIME scripts
(
make_social_card,make_favicons) and is deliberately absent fromrequirements.txt. The template's first version of this feature imported it and was therefore inert in production and on every CI leg while looking correct in review. skipis a verdict in the battery, never a pass (1.6.44 item 5).scripts/network_smoke.pyanswered an absent precondition withexpect(True, ""). A check that passes when it swept nothing reads identically to one that swept the corpus and found it clean.- Assertions of the form "this string is absent from this module"
parse, never grep (1.6.44 item 13).
conftest.live_source()strips comments AND docstrings viaast. A comment strip is not enough: a function docstring quoting a measured result tripped the UA-list guard during item 8, because good documentation explains the absence of exactly the thing such a detect hunts for.
No other fork has an upstream of its own. The private tree is
../dash-leaflet2; scripts/sync_from_rnd.py PULLS from it (dry run
by default) and refuses to overwrite the files this mirror owns
(MIRROR_OWNED: run.py, README.md, requirements.txt, lib/,
pages/, scripts/, vendor/, Dockerfile, render.yaml). Two
R&D pages are permanently withheld (DENY_DOCS), and this repo ships
its own lean /tile-selector page in place of the 3,700-line R&D lab.
Consequence for a template sync: a template change to a
MIRROR_OWNED file applies here normally — the guard is against the
R&D pull, not against upstream. But a change to docs/ must not
assume the doc set matches either repo.
CORRECTION, 2026-08-31 — "private R&D repo" was wrong. The owner
challenged the story and it does not survive measurement. There is no
private repository and this is not a mirror of one. Both directories
carry the SAME origin, github.com/pip-install-python/dash-leaflet2;
../dash-leaflet2 is a local sibling working tree, same origin,
unpushed, which scripts/sync_from_rnd.py reads BY PATH. Everything
operational above stands — it is never a drop target, its contents
still flow into docs/ through the sync, and its files are still not
this repo's to edit.
Measured here, and it is worse than "divergent": that tree has one
commit (b308393, its own root), which is not on the remote
(git ls-remote finds it nowhere) and shares zero commits with
this repo's 82 — the two histories are unrelated, and its local
origin/main ref points at its own unpushed root, which is a fiction.
Of its 106 dirty paths, 31 are UNTRACKED, and
docs/text-marker/example.py is one of them.
So the examples that are phase 2's source of truth are not in any
commit, not on any remote, and present only as loose files on this one
machine. A git clean -fd there loses them with nothing to restore
from. The phase-2 session must snapshot that tree — a pushed branch or
the owner's backup — BEFORE it edits anything, and should not assume
git checkout can undo a mistake there.
RETIRED, 2026-08-31 — scripts/sync_from_rnd.py is deleted. Owner's
decision 0af. Everything above and in the correction is now history: no
script reads that tree, so there is no pull to be destructive, nothing to
mark MIRROR_OWNED against, and no DENY_DOCS to enforce.
What retired it was the divergence map. The sibling tree turned out to be a
strict ANCESTOR with no new work — 26 of 27 changed .md files carried
lastmod: here and not there, its docs/home/home.md was still the
placeholder "This page demonstrates Home.", dl2_tiles.py and
dl2_locations.py did not exist in it at all, and its package-info.json
said 0.0.1 against this repo's 0.2.2. A pull would have stripped 26 sitemap
dates, replaced the home page with a placeholder and reverted 15 examples to
their pre-refactor state. A mechanism whose only remaining effect is to
regress the site is not a mechanism worth keeping behind a warning.
What replaces it: nothing, deliberately. This repo is simply the repo. The
two pages that were never meant to ship — docs/sprite-generator/ and the
3,700-line R&D docs/tile-selector/ lab — are not here and cannot arrive,
because nothing copies from that tree any more; this repo keeps its own lean
/tile-selector page. The sibling tree is snapshotted (9fde34f, bundle at
~/leaflet-rnd-2026-08-31.bundle) and archived.
Consequence for a template sync: the MIRROR_OWNED list is gone with the
script, so the seven template surfaces hardened into it at 115f1c4 no
longer need that protection — nothing can overwrite them. Template syncs are
unaffected: they were never what that list guarded against.
src/ts/ → webpack → dash_leaflet2/, published to PyPI as
dash-leaflet2. The template is a site and nothing else. What this
adds, all absent upstream and none of it drift: package.json /
package-lock.json / node_modules, pyproject.toml
(requires-python >=3.9 — the PACKAGE's floor, deliberately lower
than the docs site's 3.10, which is bounded by vendored
dash-clerk-auth, and lower than the container's 3.12), MANIFEST.in,
usage.py (the compiled dl2.* demo on :8060, next to run.py's
site on :8050), RELEASING.md, COMPATIBILITY.md,
scripts/compat_matrix.py + _compat_runner.py + check_release.py,
and the dash_leaflet2/metadata.json / .compat/ ignores.
The inverse of muischeduler's no-npm scope, and for the same reason
read the other way: this repo actually builds a JS bundle, so the
build toolchain is a real dependency surface. github-actions and
docker match the template.
pip is now ABSENT here as well (template 1.6.24, applied by hand
2026-08-26): on range requirements dependabot can only propose floor
RAISES, and floors move through sync specs instead. So the npm block
is the whole of this divergence.
THE FENCE WAS PROVEN ON THIS PATH, and it is worth recording that it
was not hypothetical. SYNC-1.6.22-1.6.29's sync-verbatim block
lists .github/dependabot.yml, every one of its adoption gates is
satisfied here, and the F3b fan-out ran against this repo on
2026-08-26 (PR #25, merged). It copied three files and SKIPPED this
one — the npm ecosystem is still here because the byte-owned block
below told the machine to leave it alone. Without the fence the copy
would have landed and removed the npm block silently, since removal
by byte-copy looks identical to an intended removal in a diff.
block_ai_training=False where the template ships True
(run.py, with the full rationale inline). This is not a stale
setting: dash-improve-my-llms 2.3.3 made True safe, and the
position was re-reviewed on 2026-08-23 (the ≥2.7.1 floor round) and
KEPT. The reason is what this host is — documentation for an
MIT-licensed component library, whose distribution channel is a model
recommending dash-leaflet2 to a developer who will never visit the
site. Blocking training would trade that away for a licence term the
MIT licence does not contain. A host with proprietary content should
decide the other way; scripts/network_smoke.py encodes the split so
verification reads this as a stated position rather than a miss.
This is the FLEET'S RECORDED EXCEPTION to the network-standard
block_ai_training=True, and it is visible from outside: as of
2026-08-26 robots.txt serves zero Disallow lines and names no
GPTBot / ClaudeBot / CCBot group, and both GPTBot/1.2 and
ClaudeBot/1.0 fetch / with a 200. A wire check that reads those
as a miss is reading this divergence.
disallowed_paths=[] matches the template's value today, but for a
reason worth keeping written down: Disallow: /admin/ used to be
here and was working against itself — robots.txt is public, so the
line advertised the admin path while providing no access control.
What protects that surface is auth (the board gates twice and fails
CLOSED); what keeps it out of the index is
mark_hidden("/admin/control-board").
version, base_url, reporting, on top of the fleet-standard
ok / app / backend / dash_version / build / geo /
python. All three
predate the template's health work and are kept because each answers
a question the standard payload cannot:
base_url— the origin this satellite ADVERTISES, checkable from outside. A host that resolvedBASE_URLto localhost looks healthy on every other signal while every canonical link it publishes is dead. (require_owned_base_urlrefuses the worst cases at boot; this covers the rest.)reporting— whether the traffic reporter could actually POST, so "wired but secretless" is visible without reading boot logs.version—APP_VERSION, distinct frombuild: which RELEASE, not which commit.
A wire check against this host should expect a superset, never a
mismatch. The fleet contract is that app, build and geo mean
what they mean everywhere.
The template serves the FastAPI build's /healthz from
lib/asgi_routes.py (a typed route, so it appears in Swagger). This
repo has no lib/asgi_routes.py, so the route is registered from
lib/health.py for flask / fastapi / quart alike. Same
health_payload builder, same contract — different mounting point.
A sync must not port the asgi_routes half without porting the module.
pages/markdown.py calls
_build_llms_doc(published_name(metadata.endpoint, metadata.name), ...)
where the template passes metadata.name. Without it the home page
served THREE <h1>s to a crawler: its preamble said "Home" (the nav
label) where dash-improve-my-llms injects the site brand, so the
2.7.0 prerender dedup had two different strings and could not fire.
lib/page_visibility.published_name substitutes SITE_BRAND at "/"
only; the nav keeps "Home". Same class as flexlayout's own-source
_build_llms_doc dedup, and the template should probably take it.
The template forces the wiring only when a gate env var is present.
This repo is the fleet's gate PILOT and wires the verdict path
unconditionally, so that path — and the prerender's use of it — has
been running in production, answering allow, since before
PAGE_DEFAULT_TIER flipped. The env flip was the whole change, and
flipping it back is the rollback. A sync that restores the
conditional form would silently un-wire the pilot on any host that
later clears the env.
lib/gate_layouts.py drops "and the AI assistant" from the preview
copy the template ships. This host does not wire one, and a sign-in
card that names a feature the site does not have is a broken promise
at exactly the moment it is asking for an account. (Template-class:
the template does not wire one either — see Findings.)
APP_BASE_URL first (network-standard), then
DASH_LEAFLET2_BASE_URL (this repo's legacy spelling). An ALIAS,
never a rename: render.yaml sets the legacy name on a live service,
and removing one of two env names from a running host is how it
starts advertising the wrong canonical origin — which deindexes it
silently. The template reads APP_BASE_URL alone.
The kit's contract and traps sections are BYTE-IDENTICAL to the
template's (verified by md5 of the tail from
## Network role & the behavioral contract onward). The sections
ABOVE that are this repo's, because unlike the template this repo has
a root CLAUDE.md that is already its project overview — the
Leaflet-2 API traps, the two deliverables, the build pipeline, the
mirror relationship. Porting the template's top half verbatim would
have installed a second, contradicting overview titled "Dash
Documentation Boilerplate" into every session here, describing a
project this is not and a /directives page this does not have. The
file's own first paragraph is the licence for this: identity derives
from the repo, never from this file.
Sync rule: changes to the contract or traps sections are verbatim targets. Changes to the template's project-overview sections are not-applicable here by construction.
dash_leaflet2/metadata.json (27 MB react-docgen artifact),
satellite_traffic.jsonl (the RETIRED Gen-1 ledger, kept ignored so
a stale local copy can never be committed), .compat/, and
flask_session/. The .claude allow-list and the session-document
block match the template exactly.
The template's Python window rolls: its two include legs are X.Y-1 and X.Y-2 around the fleet Python. This repo's are 3.10 and 3.13 against a 3.14 image — the second is the template's shape, the first is not.
3.10 is a real floor, not a preference: python-frontmatter 1.3
imports typing.TypeGuard, and the vendored dash-clerk-auth 1.0.5
declares requires-python >=3.10. A rolling window would stop
exercising that floor the moment the fleet Python moved twice — which
is precisely when a floor breaks quietly, because nothing else in the
tree resolves requirements.txt at its lower bound.
So tests/test_python_version.py here asserts what this fork
actually means — one leg IS the declared floor, one leg is directly
below the fleet Python — instead of the template's "within three of
the fleet minor". Both halves are still pinned, so the window can
neither collapse to one nor drift. The floor itself is stated ONCE,
as lib.constants.DOCS_PYTHON_FLOOR, and the test reads it from
there rather than repeating the literal.
Not to be confused with the PACKAGE lane. Package · Python runs
3.9–3.13, testing the dash_leaflet2 wheel's own
requires-python >=3.9 against a bare pip install dash. That
window is the package's business and is deliberately wider than the
site's; test_the_package_lane_is_out_of_scope_and_stays_wide fails
if anyone ever "aligns" it with the image. Two Pythons in one
ci.yml is the shape spec 1.6.28 describes, and this is that shape.
The template's copy has no equivalent: divergence 4 is this fork's,
so the check that proves it on a live host is too. The block asserts
robots.txt serves no ClaudeBot stanza and fingerprints the
crawler rules the running artifact produces.
This is why item 6 of SYNC-1.6.22-1.6.29 was ported here as
CONTRACT — the wake loop, the retry knobs and the SSL context, added
to this fork's file — rather than by the byte-copy the spec
recommends. A byte-copy would have deleted the assertion, and a
deleted check does not fail; it just stops being true without
telling anyone. The spec anticipates exactly this ("a fork that
replaced the tool records the divergence and ports the contract
half"); the record is this entry.
Kept as history because the retirement is the useful part. This fork found
that lib/api_reference.load_package reads the component package's
metadata.json, which here is a 27 MB react-docgen BUILD artifact that
.gitignore excludes and MANIFEST.in excludes from the wheel. On Render
it therefore does not exist, and upstream's code returned [] SILENTLY —
/api would have shipped empty at 200, with a canonical and an h1, while
every local check passed because locally the file is there.
scripts/build_api_metadata.py distils it to dash_leaflet2/api_metadata.json
(26 components, 302 props, 78 KB), which IS committed and carries the
generated stamp that is /api's sitemap lastmod.
Template 1.6.41 adopted the whole road — same SLIM_METADATA constant, same
generated stamp, same resolution order — and added a third fallback to the
classes' docstrings. lib/api_reference.py is byte-identical to template
4ac02e0 again, so this is no longer a divergence. What REMAINS this fork's is
scripts/build_api_metadata.py (the template has its own) and the fact that
metadata.json is gitignored here at all, which is what makes the extract road
load-bearing rather than decorative — pinned by
test_this_repo_really_has_no_committed_metadata_json.
Also kept as history. /changelog and /api arrived from 1.6.38 leaving a
module-level LLMS_DOC for the package to discover, which publishes the prose
but sends no lastmod, so both entered the sitemap dateless — invisible
upstream, where no test checks it, and red here under
tests/test_seo_icons.py. /changelog additionally needed its date parser
widened: this repo's CHANGELOG has always used an EM DASH, and the template's
regex took only an ASCII hyphen, so it matched every version and dropped every
date.
Template 1.6.41 took both findings and went further: the pages now call
page_visibility.register_default + page_tiers.register +
register_page_metadata(..., lastmod=...), which also brings them under the
control board's llms.txt toggle; and the heading regex generalised to the
seven shapes the fleet writes, crediting this repo's em-dash case. Both files
are byte-identical to 4ac02e0, so neither is a divergence any more.
Template 1.6.44 item 2 removes the HEAD->GET ASGI shim it added at 1.6.32. Its own note is explicit that the retirement is "gated on the pin (item 1) and not on the calendar": at dash-improve-my-llms 2.9.4 the package walks the router and adds HEAD wherever GET is allowed, including Dash's lifespan-registered page catch-all — the one case the middleware was kept for.
This fork does not take that pin. Rider 1 of the 1.6.44 drop leaves
our requirements line at dash-improve-my-llms[flask]>=2.8.0 until
the fleet pin lands at 1.6.45, so the package-side fix is not present
here and the shim is still load-bearing. Measured in-process on the
FastAPI lane at the resolved 2.8.0, 5 paths x 3 UAs, BEFORE porting:
four of fifteen pairs mismatched — /healthz 405 on all three UAs,
and / 405 to a browser while returning 200 to a crawler and to curl
(the prerender middleware answers above routing, which is the kit's
own trap). The package's routes — /llms.txt, /robots.txt,
/sitemap.xml — already passed: 2.7.2 fixed those. The residue is
exactly the two routes the package does not own.
Note this fork had NEVER carried the class; grep -rn HeadAsGet
returned zero lines. So this is not "declining to retire", it is
porting for the first time, at the moment the template drops it — and
absent-vs-retired is the confusion the ops seat flagged from
pannellum. Production is Flask, where Werkzeug derives HEAD from every
GET rule, so the wire was never affected; lib/backend.py puts the
ASGI lane one env var away, which is what makes it worth fixing.
TWO VERSION REGIMES, ONE POSTURE — and the distinction is what a
>= floor makes unavoidable. The floor permits any version from
2.8.0 up, and a fresh venv resolves 2.10.0 today, so both of
these are normal states of this repo:
- below 2.9.4 — the package does not walk the router, the shim is LOAD-BEARING, and its absence is a defect;
- at or above 2.9.4 — the package adds HEAD wherever GET is allowed, so the shim is REDUNDANT. Not wrong, not broken: the parity table is 15/15 either way. It stays INSTALLED.
The shim is retired by the PIN ROUND (1.6.45), never by whichever
version a resolver happened to pick, and never on a date — a
re-measured parity table without it is the trigger, the same rule as
run.py's _openapi_kwargs guard.
tests/test_head_get_parity.py records which regime it ran in and
xfails the "shim still required" clause above 2.9.4, so the day the
package takes over is VISIBLE in CI output as an XFAIL transition
without being a red build. It asserted that clause as a hard failure
until the ops seat mirrored this tree on a FRESH venv: our >=2.8.0
floor resolved 2.10.0 and the guard failed on every leg. A reminder
that turns a permitted dependency resolution into a red build is not
a reminder.
The loading/decoding prohibition and the stdlib-only size readers
are guard entries and live under Recorded conventions above. The
two below are this fork's own findings and belong here.
(d) The mobile console error is NOT CLEARED on this host. The template records it as "not reproduced" against its own deployed build and adds, correctly, that a fork which DOES see it must not read that line as clearance. This repo is one of the three hosts the symptom was originally reported on (the template names leaflet, llms and pannellum), so its own measurement does not transfer here and this fork must not inherit the clearance.
MEASURED HERE, 2026-09-05, in the owner's Chrome against the deployed build 2aea641 (which predates this pass):
/ desktop 4 console messages, ALL `LOG`, 0 errors
/pointer-events 390x844 15 console messages, ALL `LOG`, 0 errors
Every line is Clerk's ([Clerk Glass] Theme changed, [Clerk] Session changed, the avatar element check) plus the satellite auth handshake.
No error, no warning, on either page.
TWO HONEST LIMITS on that reading, because a clean measurement taken the wrong way is how a fork clears a defect it still has. The session was SIGNED IN, so the anonymous path is not covered; and the window was resized to 390x844 but the captured screenshot still rendered the desktop layout, so this is a narrow window rather than a confirmed phone viewport. Status: NOT REPRODUCED on this build, NOT CLEARED — re-measure signed-out, in a real device emulation, before closing it.
(e) Shipped CSS/JS are not minified, deliberately. Same posture as
the template and for the same reasons, re-checked here rather than
inherited: assets/ is text served over a gzip transfer encoding, and
a build step would trade the readable stylesheet for a saving the
encoding has already taken. This repo has a stronger version of the
template's argument — assets/leaflet2_maps.js and assets/style.css
ARE the documentation for how the showcase wires Leaflet 2, and a
reader who opens them expects the source a human wrote. Revisit if
assets/ grows past a few hundred KB.
Paths this fork owns byte-for-byte. The F3b fan-out never overwrites
a path listed here; everything else in the spec's sync-verbatim
block is the template's to update mechanically. Prose above explains
divergences; this block is the machine answer.
Repo-relative paths, one per line, # comments, no ..; exactly one
block. An EMPTY block means "the template owns every sync-verbatim
path here" — present so the absence is a statement. When the block
exists it is authoritative; a fork without it gets the conservative
mention heuristic (over-flags, never restores).
Audited 2026-08-26 against the union of the three live specs'
sync-verbatim blocks: the three kit skills, tests/test_claude_kit.py,
.github/dependabot.yml, tests/test_auth_demos.py. Exactly one of
them carries a byte-level claim in the prose above — divergence 3. The
kit skills and the kit test are TEMPLATE-owned here and byte-identical
to template HEAD (md5-verified this pass); this fork claims nothing on
them, so they stay out and the fan-out keeps them current. Two nearby
mentions are deliberately NOT entries: the fleet precedent
"muischeduler's no-npm dependabot scope" describes another fork's file,
and the /new-component skill named in the drift section lives in the
sibling working tree's .claude/rules/, not in the kit's skills/.
The cost of the one entry, written down so nobody rediscovers it: a listed path is one the fan-out will never update either. Dependabot changes therefore land here BY HAND. The first such change has now been made: template 1.6.24's pip-ecosystem removal, applied 2026-08-26 as an edit that keeps the npm block rather than the whole-file byte-copy the spec's block would have performed. That is the standing cost of this entry, and the standing procedure for it — read the template's copy, port the intent, keep divergence 3.
Re-audited 2026-08-26 against SYNC-1.6.22-1.6.29, which added
.github/dependabot.yml and tests/test_auth_demos.py to the
verbatim block. The audit's answer is unchanged: one entry.
tests/test_auth_demos.py arrived from the fan-out and is
template-owned here — this fork claims nothing on its bytes.
scripts/smoke_live.py rode the block for exactly one round (1.6.28)
and was pulled back out at 1.6.29; had it still been cargo it would
have needed an entry, because this fork's copy carries a check the
template's does not (the open-training assertion, divergence 4). It
is contract-class now, so the fence stays at one path — but the near
miss is the reason to re-run this audit every round rather than
trusting the last one.
Re-audited 2026-08-29 for SYNC-1.6.22-1.6.35 (items 12 + 13), whose
block adds tests/test_analytics_classifier.py and
tests/test_traffic_rollup_v4.py. Both arrived here as byte copies of
template HEAD and this fork claims nothing on their bytes, so the
answer is unchanged: one entry. Item 12's other two tests
(test_read_ledger.py, test_traffic_page.py) are contract-class
upstream and were ported, not copied — they call this tree's conftest
fixtures and pages/control_board.py. Item 13's
tests/test_cd_promotes_release.py is likewise a port: it parses THIS
fork's cd.yml, whose host string, wait sizing and comments are its own.
# Divergence 3: this repo builds a JS bundle, so its dependabot config
# ADDS an npm ecosystem the template's copy does not have. The 1.6.24
# rewrite is a whole-file byte-copy that would silently remove it.
- .github/dependabot.yml
# PORTED, not copied, at item 18 — each carries fork content a byte-copy
# would delete. Fenced in the same commit that ported them, per the rule
# that a path you ported belongs here before the next reclass, not after.
#
# components/header.py the satellite mark, the green wordmark, the
# `Leaflet <version>` subline, the mobile glyph,
# and the CARTO tile-theme bridge callback the
# showcase maps depend on (no template equivalent)
# components/navbar.py `nav_label()` — this fork reads `nav:` for the
# rail; otherwise template-shaped
# components/appshell.py the desktop-navbar collapse store + its two
# clientside callbacks, absent upstream
# pages/markdown.py this repo's directive set, `.. source::`
# expansion, and the published-name llms_doc call
# (divergence 7)
# lib/constants.py this site's identity, DOCS_PYTHON_FLOOR, the
# two-env BASE_URL alias (divergence 10)
- components/header.py
- components/navbar.py
- components/appshell.py
- pages/markdown.py
- lib/constants.pyWhat this host SERVES, measured — not what the template ships. The hub
used to keep this as a seeded table it could not re-measure; the fence
(template 1.6.30, item 9) homes each posture in the repo that serves
it. tests/test_claude_kit.py validates the SHAPE and holds runtime
against render.yaml; no test can tell a stale 200 from a fresh one,
so the values below carry the date they were taken.
-
ai_bots— re-measured 2026-08-30T14:25Z againsthttps://leaflet.2plot.devfor BOTH vendor UAs the fleet checks:ClaudeBot/1.0andGPTBot/1.2each answer 200 on/,/llms.txtand/healthz(six lines, all 200);robots.txtserves zeroDisallowlines and names no training UA at all. That is divergence 4 on the wire, not a miss: this host shipsblock_ai_training=Falsebecause it is documentation for an MIT-licensed component library whose distribution channel is a model recommendingdash-leaflet2.As of template 1.6.37 this is no longer a divergence in POSTURE — the fleet default flipped to allow, and the tool became per-vendor policy rather than per-class blocking. What remains recorded here is that this host got there first and has the wire history to show it. IN-PROCESS AND WIRE AGREE, all six: the app answers 200 itself, so there is no edge wall in front of this host either (the template's drop assumed a Cloudflare rule; the owner has since confirmed the feature is Enterprise-only on this plan and no zone rule exists).
-
healthz: full— and a superset at that; see divergence 5, which addsversion,base_urlandreportingto the fleet-standard payload. -
runtime: docker—render.yamlbuilds the Dockerfile, soPYTHON_VERSIONis deliberately ABSENT there (spec 1.6.28 item 5: on a Docker service nothing reads it, and a string that reads like the platform's setting and can never be true is its own defect). -
deploy: release-branch— since 2026-08-29 (template 1.6.35, item 13). Render watchesrelease; onlycd.yml'sdeployjob writes it, fast-forward, after the CI matrix is green.mainahead ofreleaseis an uncertified push pending, never drift. An absentdeploy:key would read as "this host still watches main".
ai_bots: {"/": 200, "/llms.txt": 200, "/healthz": 200, "/robots.txt": 200, "/sitemap.xml": 200}
healthz: full
runtime: docker
deploy: release-branchListed so a sync closes them rather than reading the gap as a decision. None of these are divergences.
lib/health.py::_resolved_country()reads the Flask request context only. The template takesheadersper route after the pannellum finding (its FastAPI healthz answered"no request context"forever). Production here isDASH_BACKEND=flask, so the live payload is correct — but the fastapi and quart lanes this repo registers would report the same false negative.components/appshell.pyhardcodes70where the template usesHEADER_HEIGHTfromlib/constants.py.- Missing template test modules:
test_auth_wiring.py,test_config.py,test_control_board.py,test_css_hygiene.py,test_docs_content.py,test_llms_routes.py,test_network_directory.py,test_proxy_scheme.py,test_runtime_imports.py. (test_excluded_links_hidden.pyandtest_nav_contract.pyarrived with the 1.6.38 navigation contract;lib/directives/headings.pycame with it too, so both are off this list.test_admin_nav.pywas REWRITTEN against the new admin mechanism rather than retired — see below.) (This repo has five the template does not:test_admin_nav.py,test_healthz_identity.py,test_network_surfaces.py,test_page_structure.py,test_page_visibility_reload.py—test_page_structure.pyis the template'stest_pages.pyunder this repo's name.) scripts/audit_links.pyandscripts/dev.share not ported.- The Dockerfile has no
HEALTHCHECK, andCMDbinds a bare${PORT}rather than${PORT:-8050}(SYNC-1.6.10-1.6.16 item 5). An emptyPORTcollapses the bind. This also makes SYNC-1.6.17-1.6.21 item 2 UNSATISFIABLE until it is fixed: that item asks CI to assert{{.State.Health.Status}}, which isnoneon an image that declares no healthcheck — soci.ymlstill polls{{.State.Running}}. Item 5 has to land first; the two are one change in practice. cd.yml's build-match wait is under-sized in four ways (SYNC-1.6.10-1.6.16 item 4). It does comparebuild == GITHUB_SHAagainst the body — the part that matters, and it certified the last two deploys — but: the loop is 60 x 15s where the spec wants >=100;timeout-minutes: 20where it wants >=30; a hookless deploy emits::notice::where it wants::warning::; and the verify job'sifexcludes'cancelled'but not'skipped'(muicharts' guard). A floor bump busts the pip cache, so the round with the most to prove is the one whose deploy is slowest — dash-email timed out on exactly this class.kickoff/is missing from.gitignore. The template's session-document block carries it (its.gitignoreline 169, in a separate block above the*-*.mdpatterns, which is how this list read as complete once before — batch-1's correction). Probed 2026-08-26:kickoff/probe.mdis committable in this repo today. Nothing is at risk right now because nokickoff/exists here.- The root
CLAUDE.mdadvertises.claude/rules/and a/new-componentskill that no clone of this repo has ever had. They exist in the sibling working tree; the blanket.claude/ignore (removed 2026-08-24) is why they never arrived. Either port them through the mirror or stop advertising them.