Repository navigation
feat(docs): add a bilingual documentation site and its deploy pipeline - #507
Conversation
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: remove or replace the stylesheet's untracked local-only source reference.
I found one blocking repository-rule violation, marked inline.
I reviewed the full github/main...7f9aa66a3b97 diff, including the commit added while this review was in progress; the relevant site/config callers and generated link behavior; commit history and action tag availability; AGENTS.md, CLAUDE.md, and CONTEXT routing; backward compatibility; test changes for weakening; and the documented two-stage Pages deployment architecture.
Verification at the latest head: the strict bilingual MkDocs build succeeded and generated both locales with seven translated navigation elements; 40 relevant pytest cases passed; the source-language and large-file gates passed against github/main...HEAD; and git diff --check passed. GNU make is unavailable in this environment, so I ran the exact uv commands behind the Makefile targets. The PR's docs build GitHub check is also green. I found no other blockers.
gloryfromca
left a comment
There was a problem hiding this comment.
No blockers; this can merge as far as I am concerned.
The only delta from the previously reviewed head replaces the inaccessible source citation with tracked, accurate references, so the prior blocker is resolved; I replied on and resolved that thread. I reviewed the new commit in the context of the full diff, repository rules and context documents, surrounding site/build configuration, history, backward compatibility, unchanged test strength, and the two-stage deployment architecture. No new issue emerged.
Verification at 33d8d6198534: strict bilingual MkDocs build passed with both locale trees and seven translated navigation elements; 40 focused pytest cases passed; source-language and large-file checks passed against github/main...HEAD; the replacement spec path is tracked; and git diff --check passed.
The design moves self-hosting, the web UI launch, the command reference and the repo layout out of both READMEs into a bilingual MkDocs site, leaving Quick Start where it is. The spec records what moves, which four contracts read the moved content, and which of them fails silently rather than loudly. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
Add a docs dependency group, an MkDocs Material config with English at the root and Chinese at /zh/, and two Makefile targets. The build output is gitignored because AGENTS.md section 7 forbids committing HTML. Co-authored-by: Claude (claude-sonnet-5) <noreply@anthropic.com>
The previous commit set the i18n plugin's zh language name to the native label, which scripts/check_source_language.py rejects: docs-site/ is not one of the AGENTS.md 1.3 exemption zones and mkdocs.yml is not Markdown, so the CJK label would fail CI's repository files job. Use the English label instead; the switcher still renders both locales. Adding docs-site/ as an exemption zone is the owner's call per AGENTS.md 1.3, not this branch's; if that lands later, the native label is a one-line follow-up. Co-authored-by: Claude (claude-sonnet-5) <noreply@anthropic.com>
The Global Constraints and all nine commit blocks named a literal trailer id. AGENTS.md 3.3 requires the id of the model actually writing the commit, so a literal copied from a plan is wrong for every task a different model runs, and the repository's own convention already splits them: the plan-authoring commit carries the driver's id, each delegated task carries the implementer's. Task 3 also picks up a bilingual anchor asymmetry the review found in the landing pages. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
Both defects are silent: a repo-relative link renders and 404s only on click, and a one-language page is indistinguishable from a translation behind the i18n fallback. Each guard was confirmed to fail on its defect before this landed. Co-authored-by: Claude (claude-haiku-4-5-20251001) <noreply@anthropic.com>
The Task 2 review built the site with each link planted and read the strict build's exit code rather than reasoning about it. A relative link whose target ends in .md aborts mkdocs build --strict with the file and the link named; one that does not end in .md exits 0 and 404s only on a click. Four of the eight links the migration must absolutise fall on each side, so the blanket claim was wrong for half of them. The guard is still worth having, for reasons the section now states instead of the one it had. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
Finding 1: Add guard to link test so it fails when no pages are found, matching the parity test's protection. Proved the guard works by renaming docs-site/docs away and confirming the test fails with the expected message. Finding 2: Rewrite docstring so it states what is actually true. The guard catches non-.md repository-relative links (e.g., docker/.env) that mkdocs build --strict does NOT abort on; .md-suffixed links are already caught by --strict itself. The guard also runs in the ordinary test suite without needing the docs uv group. Co-authored-by: Claude (claude-haiku-4-5-20251001) <noreply@anthropic.com>
The plan still carried the pre-review docstring and link test, so a re-run would have reintroduced the claim the review falsified and the vacuous pass it found. Both now mirror tests/test_docs_site.py byte for byte, and the task's commit-message template states the scoped rationale rather than the blanket one. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
The documentation site is bilingual by design, and its i18n config carries the language-switcher display name. mkdocs.yml is not *.md, so the blanket suffix exemption did not reach it and the gate refused the native label. The owner signed the zone; the gate list, the AGENTS.md list and the pin table move together because a contract test holds all three equal. Co-authored-by: Claude (claude-sonnet-5) <noreply@anthropic.com>
Copied from both READMEs unchanged apart from three mechanical edits: dropping any trailing Back-to-top block, demoting headings one level under each page's new H1, and making the eight repository-relative links absolute so they resolve from a published page rather than only from the repository root. The nav and the two index pages gain their entries here rather than in the scaffolding commit, because --strict rejects a nav entry whose file does not exist. Co-authored-by: Claude (claude-sonnet-5) <noreply@anthropic.com>
Co-authored-by: Claude (claude-haiku-4-5-20251001) <noreply@anthropic.com>
Update upload-pages-artifact to v5.0.0 and deploy-pages to v5.0.1 for node20 runtime compatibility past 2026-09-23. Add Python 3.12 install step to match repository CI standards. Give deploy job its own non-cancellable concurrency group to prevent API wedges. Co-authored-by: Claude (claude-haiku-4-5-20251001) <noreply@anthropic.com>
The plan specified actions/upload-pages-artifact@v3 and actions/deploy-pages@v4, both of which declare the node20 runtime that GitHub removes from its runners on 2026-09-23. upload-pages-artifact runs in the build job, so past that date every pull request's docs build would fail rather than only the deploy. The plan now pins the v5 pair, carries the deploy job's own non-cancelling concurrency group, and adds the Python pin that every other job in ci.yml already runs, with the reasoning beside them so a re-run does not restore any of the three. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
The docs-serve and docs-build targets called uv without --frozen or --python, the only Makefile uv run lines besides beta that did not. A bare uv run resolves 3.13 on a developer box while the repository and its CI use 3.12, so a local site build could diverge from the one the workflow produces. The workflow itself is unaffected: it inlines its own pinned command instead of calling these targets. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
The site now follows the shape taken from docs.newapi.pro: a top row of section tabs, a grouped sidebar, and a landing page that is a directory of linked cards rather than prose. Five pages do not justify seven tabs, so the sections are three. The brand skin remaps Material's own CSS custom properties onto the EverMind token set, then resets the corners Material hardcodes, because square geometry is the strongest identity cue in that system. It has to work this way: overrides/*.html is how Material is normally customised, and scripts/check_large_files.py blocks committing HTML. This also closes a defect no page-level review could see. The navigation labels live in mkdocs.yml, not in any page, so comparing the two languages' Markdown found nothing while the Chinese site rendered an English sidebar. nav_translations fixes it and the build now reports seven translated navigation elements. The Chinese title drops the italic serif accent word: Cormorant Garamond has no CJK glyphs, so it would fall back to another face. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
The class names in the pages and the rules in evermind.css are a contract with no build step between them: a rename on either side errors nowhere and reddens nothing, and the only sign is an element rendering unstyled on a page nobody happens to be looking at. The guard compares the two sets in both directions, so it also catches a rule no page reaches. Proved load-bearing by mutating each side in turn. Renaming .em-eyebrow in the stylesheet and class="em-standfirst" in index.md each turned it red, and it is green again with both restored. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
evermind.css imported Bungee Shade and held it in a token no rule read, so every page load paid for a face that never reached a glyph. The brand reserves it for a single large wordmark, and this site takes its layout from a reference that has no hero to carry one. Re-add the import and the token together if a wordmark band is ever wanted. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
The spec described the site's files and its deploy path and said nothing about how it looks or navigates, so the sectioned layout, the card directory and the brand skin had no design record at all. The load-bearing entry is the constraint. Material customises through theme.custom_dir with Jinja partials under overrides/, those partials are .html, and check_large_files.py holds .html in BLOCKED_ASSET_EXTENSIONS and fails any commit adding one outside bridge/, ui-web/ and ui-tui/. A maintainer reaching for a template override meets a gate rather than a review comment, so the rule belongs in the design document and not in the stylesheet's own header. The section also records why navigation labels need nav_translations: they are the one piece of reader-visible text living in mkdocs.yml, so comparing the two languages' Markdown cannot detect their absence. The guard list gains the sixth entry it was missing. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
mkdocs.yml configured pymdownx.emoji through !!python/name:, a tag PyYAML's safe loader has no constructor for, so pre-commit's check-yaml failed the pull request while mkdocs itself built clean. The extension was there to render one arrow glyph in front of each card link. The reference layout this site follows carries no icon on its cards at all, so removing the extension and the glyphs closes the conflict at its source instead of excluding the file from a repository-wide check or passing --unsafe to a hook every other yaml file benefits from. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
The header pointed at .claude/skills/evermind-web-design/references/tokens.css for the brand tokens. That path is gitignored and git ls-files returns nothing under it, so no reviewer or maintainer can open it, and AGENTS.md section 1.1 forbids a source comment that references a locally-visible-only path. The tokens this skin uses are declared in the file's own :root block, and the Presentation section of docs/specs/2026-09-18-docs-site-design.md already carries the CSS-only constraint and its rationale. The header names those two instead. Both are tracked, checked with git ls-files --error-unmatch. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
The revision-date plugin reads the log of the file it is rendering, so the deploy checkout needs full history rather than the default shallow clone. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
The header becomes a fixed left rail carrying the brand, the search box and the navigation tree, and the table of contents gets one continuous polyline clipped to the headings on screen. The mark is a data URI because section 7 keeps image files out of the repository. The wordmark next to it shares the mark's centre line: both hang from the same row top, so the wordmark's line box is the mark's box and the leading it drops is added back below, which leaves the search box where it was. Controls relocated out of the header keep the popups Material sized for a top bar, and a popup that lands off-viewport still answers querySelector, so the new integration file hit-tests each control at the point a reader clicks. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
Quick start, self-hosting, Docker, the WebUI, the command reference, the runtime architecture, the repository layout, the sandbox manual, the developer workflow, the proactivity pair, the self-evolution map and the tracing API now live on the site, each with a Chinese twin. A CJK heading slugifies to nothing, so Markdown numbers it positionally and an inserted heading silently renumbers every anchor below it. Each Chinese heading therefore pins the anchor its English twin gets for free, and a new guard fails when one does not. Documents that stay in the repository are named as plain paths rather than linked, so the site never sends a reader out to a file it does not host. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
Each readme points at the language a reader of that readme wants. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
33d8d61 to
5887e91
Compare
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: make the docs-site unit test importable in the standard unit environment.
I found one new blocker in the expanded revision, marked inline.
I reviewed the full github/main...5887e91b0a64 diff and the four post-review commits, including repository rules and context documents, the generated site and build/deploy callers, relevant history, backward compatibility, test strength and discovery, and the rail/browser architecture. The previously resolved stylesheet thread remains resolved.
Verification: the strict bilingual MkDocs build passed and translated 17 navigation elements; the source-language and large-file gates plus git diff --check passed; and 44 focused tests passed after the docs group had been installed. That last environment masks the blocker: an isolated reproduction matching the unit job (--all-extras --dev --no-group docs) aborts collection of tests/test_docs_site.py with ModuleNotFoundError: markdown. The browser suite collected 13 tests locally but all 13 skipped because this runner has no Chrome binary; the PR records a separate 13-pass run.
This is a round-five blocker on all three required grounds: this revision adds the import, the ordinary unit shard reaches it, and the shard cannot run past collection without a code or dependency correction. I found no other new blocker.
The guard imports the slugify the build itself calls, and markdown reached the venv only through the docs group. The unit job syncs --all-extras --dev without it, so collection aborted there and the guard protected nothing: importing the real function is the point, since a hand-rolled copy can drift from what mkdocs actually does. Declaring markdown as a dev dependency makes the module import in the unit job. Proved by mutating an anchor under the job's own sync flags: the guard fails on the mutation and passes with it restored. Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
No blockers; this can merge as far as I am concerned.
The dependency fix at 4a2c0f75e7c8 is correct: markdown is now a direct dev dependency, so the docs-site guard imports and runs in the ordinary unit environment without relying on a prior docs build. The exact isolated reproduction passes 5 tests; the 44-test focused set, strict bilingual MkDocs build, source-language gate, large-file gate, and git diff --check all pass. I replied to and resolved the settled unit-environment finding.
This round covered the revision delta and lock metadata, the standard CI unit caller, dependency/backward-compatibility impact, and whether test coverage was weakened; it was not. The prior full-diff review covered the repository rules and context files, docs/deploy callers and history, compatibility, and architectural constraints. I found no new plain error or blocker.
ZuyiZhou
left a comment
There was a problem hiding this comment.
Approving. Reviewed independently rather than taking the description at its word.
Verified locally at the pushed head:
make docs-build(--strict) builds clean; bothsite/index.htmlandsite/zh/index.htmlare produced.- Anchor parity measured on the built HTML, not the Markdown: 14 page pairs, 133 h2-h6 anchors, every one identical across the two languages, and none of the positional
_1/_2form the pinning exists to prevent. - The Chinese sidebar renders Chinese and the document carries
lang="zh", so the navigation-label defect is actually closed. - 31 unit tests pass (
test_docs_site.py,test_source_language_check.py), andmake check-large-files/make check-source-languageboth exit 0. - Every
raven <command>in the command reference exists in the real CLI, and the subcommands were checked against--helptoo:gateway status|reload|stop,agents new,plugin auth,mcp bridge,ops connection, andtracing compact(an action argument, correctly documented as one). - Section 7 is clean: no new file over 100 KiB, no
.htmlor.svgcommitted, the brand mark is a 35-characterdata:URI. - The AGENTS.md zone and
EXEMPT_PREFIXESmoved together and the contract test holds them equal. Action versions match the other 18 workflows.
Three non-blocking notes, none worth another round:
- The
docs-site/exemption prefix is wider than the AGENTS.md entry describes. The stated need is the navigation labels inmkdocs.yml; the prefix also quietly exemptsstylesheets/andjavascripts/.docs-site/mkdocs.ymlwould match the text exactly. - Two guards in
tests/test_docs_site.pydisagree in their remediation advice: the relative-link test tells you to make the target an absolute github.com URL, and the external-link test then rejects exactly that. Both pass today because no page has a link of either kind, so it is only the message that misleads. CHROME = "/usr/bin/google-chrome"means the browser suite silently skips on macOS rather than running. Combined withnorecursedirsexcludingtests/integration/, the rail's coupling to Material's internal class names has no guard that runs anywhere by default.
One thing to know at merge time, already disclosed: the workflow-level cancel-in-progress: true outranks the deploy job's own cancel-in-progress: false, so two merges landing close together can cancel a deploy in flight. The following push redeploys, so it self-corrects.
Pages still needs Source: GitHub Actions before the README link resolves.
#507) ## Summary Stands up a bilingual MkDocs site under `docs-site/`, published to GitHub Pages by a workflow that builds on every pull request and deploys only from `main`. Fourteen topics ship in English and Chinese: the quick start, self-hosting, Docker, the WebUI, the sandbox manual, the runtime architecture, the command reference, the repository layout, the developer workflow, the proactivity design and reference pair, the self-evolution map and the tracing API. This pull request is additive. Both READMEs keep their prose and gain one link to the site in the header row; trimming them is deliberately a second pull request, so the site can be confirmed live before anything depends on it. Key decisions: - **`docs-site/`, not `docs/`.** `docs/README.md` defines `docs/` as design notes and dated records, and `docs/plans/` is an archive explicitly not held to today's layout. A user manual has the opposite lifecycle. - **Full bilingual parity**, via the `mkdocs-static-i18n` suffix structure (`page.md` beside `page.zh.md`). Parity decays immediately without a guard, so a test fails when a page has no twin. - **Anchors are pinned on the Chinese side.** A CJK heading slugifies to nothing, so Markdown numbers it `_1`, `_2`, and inserting one heading renumbers every anchor below it, silently breaking links readers already hold. Each Chinese heading therefore states the anchor its English twin gets for free: 133 heading anchors, identical across the two languages, none positional. - **A left rail, not a top bar.** The header carries the brand, the search box and the navigation tree down the left; the table of contents on the right is one continuous polyline clipped to the headings currently on screen. - **No template overrides.** Material customises through `theme.custom_dir` with Jinja partials, those partials are `.html`, and `scripts/check_large_files.py` holds `.html` in `BLOCKED_ASSET_EXTENSIONS`. The skin is therefore one stylesheet remapping Material's own custom properties, plus one script for the table-of-contents rail. The brand mark is a `data:` URI for the same reason. - **An owner-signed `docs-site/` exemption zone** in AGENTS.md section 1.3. The i18n config carries the Chinese navigation labels, and `mkdocs.yml` is not `*.md`, so the blanket suffix exemption does not reach it. A contract test holds the AGENTS.md list and `EXEMPT_PREFIXES` equal, so both moved together. - **The site never links out to a file it does not host.** Documents that stay in the repository are named as plain paths rather than linked, and a guard fails a page that links to an external webpage or a repository-relative path. Two defects found and closed here rather than after publication. The Chinese site rendered an English sidebar: navigation labels live in `mkdocs.yml`, not in any page, so comparing the two languages' Markdown finds nothing and only the rendered output shows it. And a control could be present, sized, animated and answer `querySelector` while being unclickable, because a popup Material sized for a top bar landed outside the viewport once the header became a rail. ## Type - [ ] Fix - [x] Feature - [ ] Docs - [ ] CI / tooling - [ ] Refactor - [ ] Other ## Verification All commands run at the pushed head, rebased onto `origin/main`. ``` make check-large-files exit 0 make check-source-language exit 0 make docs-build exit 0, 0 errors docs-site/site/index.html and docs-site/site/zh/index.html both present mkdocs_static_i18n: Translated 17 navigation elements to zh uv run pytest tests/test_docs_site.py tests/test_source_language_check.py \ tests/test_readme_scope_canon.py tests/test_docker_runtime.py \ tests/test_living_docs.py 44 passed uv run pytest tests/integration/test_docs_site_controls_e2e.py 13 passed pre-commit run --files <changed files> all hooks pass git diff --check clean ``` Anchor parity was measured on the built HTML rather than assumed: 14 page pairs, 133 heading anchors compared at h2 through h6, every one identical between the two languages and none positional. The controls are hit-tested rather than queried. `document.elementFromPoint` at the exact point a reader clicks must return the control itself, which is the only check that catches an off-viewport popup; the language switcher, the search panel, the repository link and the table-of-contents rail each pass it. The brand lockup is measured, not eyeballed. A failing test was written first and reported the wordmark sitting 4.00px below the mark's centre line; it is 0.00px after the fix, and a 4x screenshot puts the residual optical offset at 0.25px. Every guard this branch adds was confirmed to fail first. The brand-class guard was mutated from both sides in turn: renaming `.em-eyebrow` in the stylesheet turned it red, renaming `class="em-standfirst"` in `index.md` turned it red, and it is green again with both restored. The anchor guard was shown to catch both failure modes, a missing anchor and a wrong one. - [x] Relevant tests pass locally - [x] Relevant lint / type checks pass locally - [x] User-facing docs or screenshots are updated when needed ## Risk No behaviour change to any shipped code path. Nothing imports `docs-site/`, the new Makefile targets are additive, and the only change outside `docs-site/` and its tests is one link added to each README's header row. Rollback is deleting the branch: the site does not exist until Pages is enabled with `Source: GitHub Actions`, and every other change is inert without it. Disclosed residue, checked and deliberately not changed: - The README header now links to `https://evermind-ai.github.io/Raven/`, which 404s until Pages is enabled. It is the same URL the Documentation section already carries. - The `deploy` job is skipped on pull requests by design, so a green check here does not prove deployment works. The first real evidence is the `deploy` job's own conclusion on the `main` run after merge. - GitHub Pages is not enabled on this repository. Measured: `GET /repos/.../pages` returns 404. Under `Deploy from a branch` the uploaded artifact is silently ignored while the workflow still reports success, so the source must be set to `GitHub Actions`. - `tests/integration/` is excluded by `norecursedirs`, so the browser suite is a local guard and never runs in CI. - The self-hosting page's Makefile target, docker path and port claims are unguarded. They were equally unguarded in the README they came from, and the owner ruled against adding a guard for them. - The self-evolution SOP and the benchmark contract stay in the repository and are named as plain paths from the pages that reference them. The SOP is a translation of an upstream project's internal document and carries redaction placeholders, which is a publication decision rather than a formatting one. - `docs/plans/` still shows the pre-restyle `mkdocs.yml`. CONTEXT.md defines that directory as an archive of the tree as it stood, with an explicit rule against updating an old plan to match a later change. - The Chinese pages drop the brand's italic serif accent word. Cormorant Garamond carries no CJK glyphs, so it would fall back to another face without any sign. - The code font is Material's default Roboto Mono. The brand names four typefaces and no monospace, so none was invented for it. ## Related Issues N/A --------- Co-authored-by: Claude (claude-opus-5[1m]) <noreply@anthropic.com>
Summary
Stands up a bilingual MkDocs site under
docs-site/, published to GitHub Pagesby a workflow that builds on every pull request and deploys only from
main.Fourteen topics ship in English and Chinese: the quick start, self-hosting,
Docker, the WebUI, the sandbox manual, the runtime architecture, the command
reference, the repository layout, the developer workflow, the proactivity design
and reference pair, the self-evolution map and the tracing API.
This pull request is additive. Both READMEs keep their prose and gain one link
to the site in the header row; trimming them is deliberately a second pull
request, so the site can be confirmed live before anything depends on it.
Key decisions:
docs-site/, notdocs/.docs/README.mddefinesdocs/as designnotes and dated records, and
docs/plans/is an archive explicitly not heldto today's layout. A user manual has the opposite lifecycle.
mkdocs-static-i18nsuffix structure(
page.mdbesidepage.zh.md). Parity decays immediately without a guard, soa test fails when a page has no twin.
nothing, so Markdown numbers it
_1,_2, and inserting one headingrenumbers every anchor below it, silently breaking links readers already hold.
Each Chinese heading therefore states the anchor its English twin gets for
free: 133 heading anchors, identical across the two languages, none
positional.
and the navigation tree down the left; the table of contents on the right is
one continuous polyline clipped to the headings currently on screen.
theme.custom_dirwithJinja partials, those partials are
.html, andscripts/check_large_files.pyholds
.htmlinBLOCKED_ASSET_EXTENSIONS. The skin is therefore onestylesheet remapping Material's own custom properties, plus one script for the
table-of-contents rail. The brand mark is a
data:URI for the same reason.docs-site/exemption zone in AGENTS.md section 1.3. Thei18n config carries the Chinese navigation labels, and
mkdocs.ymlis not*.md, so the blanket suffix exemption does not reach it. A contract testholds the AGENTS.md list and
EXEMPT_PREFIXESequal, so both moved together.in the repository are named as plain paths rather than linked, and a guard
fails a page that links to an external webpage or a repository-relative path.
Two defects found and closed here rather than after publication. The Chinese
site rendered an English sidebar: navigation labels live in
mkdocs.yml, not inany page, so comparing the two languages' Markdown finds nothing and only the
rendered output shows it. And a control could be present, sized, animated and
answer
querySelectorwhile being unclickable, because a popup Material sizedfor a top bar landed outside the viewport once the header became a rail.
Type
Verification
All commands run at the pushed head, rebased onto
origin/main.Anchor parity was measured on the built HTML rather than assumed: 14 page pairs,
133 heading anchors compared at h2 through h6, every one identical between the
two languages and none positional.
The controls are hit-tested rather than queried.
document.elementFromPointatthe exact point a reader clicks must return the control itself, which is the
only check that catches an off-viewport popup; the language switcher, the search
panel, the repository link and the table-of-contents rail each pass it.
The brand lockup is measured, not eyeballed. A failing test was written first
and reported the wordmark sitting 4.00px below the mark's centre line; it is
0.00px after the fix, and a 4x screenshot puts the residual optical offset at
0.25px.
Every guard this branch adds was confirmed to fail first. The brand-class guard
was mutated from both sides in turn: renaming
.em-eyebrowin the stylesheetturned it red, renaming
class="em-standfirst"inindex.mdturned it red, andit is green again with both restored. The anchor guard was shown to catch both
failure modes, a missing anchor and a wrong one.
Risk
No behaviour change to any shipped code path. Nothing imports
docs-site/, thenew Makefile targets are additive, and the only change outside
docs-site/andits tests is one link added to each README's header row.
Rollback is deleting the branch: the site does not exist until Pages is enabled
with
Source: GitHub Actions, and every other change is inert without it.Disclosed residue, checked and deliberately not changed:
https://evermind-ai.github.io/Raven/, which404s until Pages is enabled. It is the same URL the Documentation section
already carries.
deployjob is skipped on pull requests by design, so a green check heredoes not prove deployment works. The first real evidence is the
deployjob'sown conclusion on the
mainrun after merge.GET /repos/.../pagesreturns 404. Under
Deploy from a branchthe uploaded artifact is silentlyignored while the workflow still reports success, so the source must be set to
GitHub Actions.tests/integration/is excluded bynorecursedirs, so the browser suite is alocal guard and never runs in CI.
unguarded. They were equally unguarded in the README they came from, and the
owner ruled against adding a guard for them.
are named as plain paths from the pages that reference them. The SOP is a
translation of an upstream project's internal document and carries redaction
placeholders, which is a publication decision rather than a formatting one.
docs/plans/still shows the pre-restylemkdocs.yml. CONTEXT.md defines thatdirectory as an archive of the tree as it stood, with an explicit rule against
updating an old plan to match a later change.
carries no CJK glyphs, so it would fall back to another face without any sign.
typefaces and no monospace, so none was invented for it.
Related Issues
N/A