Originally created by: TheoV823
The mobile-sticky-nav bug has been fixed three times so far (e5970e2, a9d27a3, #125) and kept coming back. Investigation traced this to two propagation paths that this PR closes:
scripts/create_mneme_article.py was fetching `index.html` live from the cPanel production server and splicing its full `` block into every new article. Whatever was deployed at the moment of generation became the template — including any CSS still buggy on production. This PR points the template source at the local repo (`site/index.html`) instead, binding article generation to the repo's reviewed state.
New pages were also being hand-scaffolded by copying nearby older pages whose `<style>` blocks still contained the bug. There's no way to programmatically prevent that, so this PR adds a CI lint that catches the reintroduction at PR time:</p> <ul> <li>`scripts/check_sticky_nav.py` — greps `site/*<em>/</em>.html` for the two known bug variants and exits non-zero on any hit (mirrors the existing `scripts/check_encoding.py` pattern).</li> <li>`.github/workflows/sticky-nav-check.yml` — runs the lint on every PR to `main` and on direct push to `main`.</li> </ul> <h2 id="h-dependency-on-pr-125">Dependency on PR <a class="alink strikethrough" href="/p/mnemehq/tickets/125/">[#125]</a></h2> <p>This PR's lint will <strong>fail CI on origin/main</strong> until <a href="https://github.com/TheoV823/mneme/pull/125">#125</a> lands, because `origin/main` still has 59 files with the buggy pattern. <strong>Merge order: <a class="alink strikethrough" href="/p/mnemehq/tickets/125/">[#125]</a> first, then this PR.</strong> After <a class="alink strikethrough" href="/p/mnemehq/tickets/125/">[#125]</a> merges and this branch is rebased, CI will pass and the lint becomes a permanent guard.</p> <h2 id="h-files">Files</h2> <ul> <li><strong>Modified:</strong> `scripts/create_mneme_article.py` (one block replaced, +8 lines of explanatory comment)</li> <li><strong>New:</strong> `scripts/check_sticky_nav.py` (80 lines), `.github/workflows/sticky-nav-check.yml` (33 lines)</li> </ul> <h2 id="h-test-plan">Test plan</h2> <ul> <li><span>[ ]</span> Verify the lint exits 1 when a buggy pattern is present (smoke-tested locally: `python scripts/check_sticky_nav.py` against current origin/main returns exit 1 and lists 59 hits).</li> <li><span>[ ]</span> Verify the lint exits 0 when the buggy pattern is absent (smoke-tested locally: after applying the <a class="alink strikethrough" href="/p/mnemehq/tickets/125/">[#125]</a> fix in-place, the lint returns OK and exit 0).</li> <li><span>[ ]</span> After <a class="alink strikethrough" href="/p/mnemehq/tickets/125/">[#125]</a> merges and this branch is rebased, the workflow run on the PR should be green.</li> <li><span>[ ]</span> Manually run `python scripts/create_mneme_article.py` (if you have the cPanel token) and confirm the generated article's HEAD now matches the repo's `site/index.html` rather than whatever is live.</li> </ul> <h2 id="h-out-of-scope">Out of scope</h2> <p>A canonical `site/_template/concept-page.html` scaffold — recommended for fully killing the human-driven propagation path but lifted to a separate discussion since it touches contributor workflow. The CI lint here gives equivalent protection at a fraction of the change surface.</p> <p>\U0001F916 Generated with <a href="https://claude.com/claude-code">Claude Code</a></p></style>
Originally posted by: github-actions[bot]
mneme self-governance check
Mode:
warn- verdicts are visible but do not block merge. Rollout plan:.mneme/README.md.Summary: 0 pass, 0 warn, 2 fail, 0 unknown
scripts/check_sticky_nav.pyscripts/create_mneme_article.pyDetails
FAIL [site_perf_001] anti_pattern "inline <script> running animation or DOM-mutation logic at parse time" -- trigger: time Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. FAIL [site_perf_001] anti_pattern "synchronous Google Fonts CSS link in <head>" -- trigger: css Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. FAIL [site_perf_001] anti_pattern "backdrop-filter on nav/menus applied unconditionally on mobile (GPU cost)" -- trigger: nav Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. FAIL [site_perf_001] anti_pattern "scripts before <link rel=preconnect> hints" -- trigger: scripts Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. WARN [site_perf_001] constraint "No blocking scripts in <head> before preconnect hints" -- trigger: scripts Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. FAIL [deploy_001] anti_pattern "python scripts/deploy_site.py" -- trigger: python deploy_site.py must always be run from the main repo root (C:/dev/mneme), never from a worktree directory FAIL [encoding_001] anti_pattern "Set-Content without -Encoding" -- trigger: encoding All automation that reads or writes text files must specify the encoding explicitly. UTF-8 for all site, doc, config, and source files in this repo. FAIL [encoding_001] anti_pattern "open() without encoding= in Python" -- trigger: encoding All automation that reads or writes text files must specify the encoding explicitly. UTF-8 for all site, doc, config, and source files in this repo. FAIL [encoding_001] anti_pattern "writeFileSync without encoding in Node.js" -- trigger: encoding All automation that reads or writes text files must specify the encoding explicitly. UTF-8 for all site, doc, config, and source files in this repo. FAIL [encoding_001] anti_pattern "implicit encoding in any automation file write" -- trigger: encoding All automation that reads or writes text files must specify the encoding explicitly. UTF-8 for all site, doc, config, and source files in this repo. Result: FAIL </details> <details><summary><code>scripts/create_mneme_article.py</code> — FAIL</summary> FAIL [site_perf_001] anti_pattern "inline <script> running animation or DOM-mutation logic at parse time" -- trigger: inline Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. FAIL [site_perf_001] anti_pattern "container divs with no height before JS populates them" -- trigger: container Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. FAIL [site_perf_001] anti_pattern "synchronous Google Fonts CSS link in <head>" -- trigger: css Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. FAIL [site_perf_001] anti_pattern "backdrop-filter on nav/menus applied unconditionally on mobile (GPU cost)" -- trigger: nav Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. FAIL [site_perf_001] anti_pattern "scripts before <link rel=preconnect> hints" -- trigger: before Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. WARN [site_perf_001] constraint "No blocking scripts in <head> before preconnect hints" -- trigger: head Site pages with inline JavaScript must defer animations and pre-size dynamic containers to prevent CLS and TBT regressions on mobile. FAIL [deploy_001] anti_pattern "python scripts/deploy_site.py" -- trigger: site deploy_site.py must always be run from the main repo root (C:/dev/mneme), never from a worktree directory Result: FAIL </details> <sub>Generated by `.github/workflows/mneme-check.yml` · query = PR title + file path · scope = repo-governance paths.</sub> <!-- Sticky Pull Request Commentmneme-check --> </script>scripts/check_sticky_nav.py— FAILTicket changed by: TheoV823