You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of the Documentation Site workstream (see the epic) · decided in ADR-0009 · specified in the roadmap. Depends on docs-s1 (tier restructure + Starlight scaffold + adapter).
Makes the manual something a user actually has: a browser-openable copy inside every release, reachable from the Help menu, with reference pages that link out to their full guides.
As-built facts you must know
Verified 2026-07-21.
Today's help staging (editor/CMakeLists.txt:272-282, POST_BUILD): macOS <bundle>/Contents/Resources/help/, Windows/Linux <exe dir>/help/ — and it copies onlyroadmaker.qch + roadmaker.qhc, no HTML.
Install rules (editor/CMakeLists.txt:288-307): install(TARGETS roadmaker-editor BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}); then if(NOT APPLE) install(FILES ${_rm_qch} ${_rm_qhc} DESTINATION bin/help). macOS relies on the bundle being copied wholesale.
The release smoke test already asserts help paths — .github/workflows/release.yml:131 ("Smoke test packaged binary (--version + bundled help)") checks roadmaker-editor.app/Contents/Resources/help/roadmaker.qch (:146-147), squashfs-root/usr/bin/help/roadmaker.qch (:156-157), <root>/help/roadmaker.qch (:165-166), plus QtSql + the qsqlite driver. Extend this step for the manual; do not write a parallel one.
The in-app viewer is a QTextBrowser subclass resolving qthelp:// in loadResource(); the collection is located at editor/src/help/help_locator.cpp:26-35 (macOS ../Resources/help, else <exe dir>/help) and copied to a writable versioned dir under AppDataLocation (:47-64). The manual-path resolver should mirror this shape, not invent a new one.
Help action + F1 are registered through shortcut_registry at editor/src/app/actions.cpp:347-349; the new menu action goes through the same registry — never hardcode a shortcut.
The .qhp renderer emits no heading anchors, so a bridge link with a #fragment lands at the top of the target page. Design the bridge convention to not depend on fragments.
Deliverables
1. build:local — the file:// reader build
Per ADR-0009: build.format: 'file' plus fully relative asset and link references so the site opens straight off disk with no server.
Starlight does not ship this guarantee: evaluate a maintained relative-links integration versus an idempotent post-processing step, and justify the choice in the PR. If you write a post-processor, it must be idempotent (running it twice equals running it once) and covered by a test that proves it.
Search is disabled in this variant — Pagefind cannot index over file:// in mainstream browsers. Put a short note on the local landing page saying search lives on the web docs. Never ship a search box that does nothing.
CI check: fail the build if any root-absolute path (/… in href/src) survives in the local output.
2. Release packaging
Behind ROADMAKER_BUNDLE_MANUAL, default OFF, so a developer build never needs Node. CMake never invokes npm: the packaging job builds the manual with Node first and passes the prebuilt folder in as a path.
Install layout:
macOS: RoadMaker.app/Contents/Resources/manual/
Linux: share/roadmaker/manual/
Windows: manual/ beside the executable
Extend the existing release smoke test (fact 3) to assert manual/index.html exists at the right place on each platform.
3. Help-menu action
"Open manual in browser" (final wording your call), opening manual/index.html via QDesktopServices::openUrl, registered through shortcut_registry.
Per-platform path resolution, factored into a pure, unit-tested function (given an executable dir and a platform, return the expected manual path) — not inline in a slot. Follow the help_locator shape.
Graceful dev-build fallback: when the manual folder is absent, show a friendly pointer at the web docs. It must not fail silently and must not show a raw error.
F1 behavior is untouched.
Editor tests run headless (QT_QPA_PLATFORM=offscreen); test the resolver and the fallback decision, not the browser launch.
4. Reference→guide bridge convention
A standard trailing section on reference pages linking the matching guide:
On the site: an ordinary link.
In the .qch viewer: an external-browser link into the packaged manual (QDesktopServices::openUrl), i.e. it must survive helpc's link rewriting as an external URL rather than being rewritten to a qthelp:// page or a GitHub blob URL. Decide the marker (a distinct URL scheme, an absolute URL, a generator-recognized section) and document it.
CI checks that every bridge target exists. A reference page pointing at a guide that was renamed must fail the build.
Apply the convention to the reference pages that have a matching guide; do not invent guides that do not exist.
Acceptance
A packaged build on at least one platform opens the manual from the Help menu, and the same build still opens in-app help with F1.
The local build passes the no-absolute-paths check; opening index.html directly from the filesystem navigates correctly between pages and images.
The dev-build fallback shows the friendly pointer (covered by a test).
Bridge targets verified in CI; a deliberately broken bridge link fails the build.
Release smoke test asserts the manual on all three platforms.
F1 and the .qch pipeline are behaviorally unchanged.
Out of scope — do not touch
Web publishing, versioning, versions.json, Amplify, any publishing workflow (docs-s3).
The authoring guide, dependency cadence, IP sweep (docs-s4).
Re-tiering or moving pages — docs-s1 owns the structure.
Part of the Documentation Site workstream (see the epic) · decided in ADR-0009 · specified in the roadmap. Depends on
docs-s1(tier restructure + Starlight scaffold + adapter).Makes the manual something a user actually has: a browser-openable copy inside every release, reachable from the Help menu, with reference pages that link out to their full guides.
As-built facts you must know
Verified 2026-07-21.
editor/CMakeLists.txt:272-282, POST_BUILD): macOS<bundle>/Contents/Resources/help/, Windows/Linux<exe dir>/help/— and it copies onlyroadmaker.qch+roadmaker.qhc, no HTML.editor/CMakeLists.txt:288-307):install(TARGETS roadmaker-editor BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}); thenif(NOT APPLE) install(FILES ${_rm_qch} ${_rm_qhc} DESTINATION bin/help). macOS relies on the bundle being copied wholesale..github/workflows/release.yml:131("Smoke test packaged binary (--version + bundled help)") checksroadmaker-editor.app/Contents/Resources/help/roadmaker.qch(:146-147),squashfs-root/usr/bin/help/roadmaker.qch(:156-157),<root>/help/roadmaker.qch(:165-166), plus QtSql + the qsqlite driver. Extend this step for the manual; do not write a parallel one.QTextBrowsersubclass resolvingqthelp://inloadResource(); the collection is located ateditor/src/help/help_locator.cpp:26-35(macOS../Resources/help, else<exe dir>/help) and copied to a writable versioned dir underAppDataLocation(:47-64). The manual-path resolver should mirror this shape, not invent a new one.F1are registered throughshortcut_registryateditor/src/app/actions.cpp:347-349; the new menu action goes through the same registry — never hardcode a shortcut..qhprenderer emits no heading anchors, so a bridge link with a#fragmentlands at the top of the target page. Design the bridge convention to not depend on fragments.Deliverables
1.
build:local— the file:// reader buildPer ADR-0009:
build.format: 'file'plus fully relative asset and link references so the site opens straight off disk with no server.Starlight does not ship this guarantee: evaluate a maintained relative-links integration versus an idempotent post-processing step, and justify the choice in the PR. If you write a post-processor, it must be idempotent (running it twice equals running it once) and covered by a test that proves it.
Search is disabled in this variant — Pagefind cannot index over
file://in mainstream browsers. Put a short note on the local landing page saying search lives on the web docs. Never ship a search box that does nothing.CI check: fail the build if any root-absolute path (
/…inhref/src) survives in the local output.2. Release packaging
Behind
ROADMAKER_BUNDLE_MANUAL, defaultOFF, so a developer build never needs Node. CMake never invokes npm: the packaging job builds the manual with Node first and passes the prebuilt folder in as a path.Install layout:
RoadMaker.app/Contents/Resources/manual/share/roadmaker/manual/manual/beside the executableExtend the existing release smoke test (fact 3) to assert
manual/index.htmlexists at the right place on each platform.3. Help-menu action
"Open manual in browser" (final wording your call), opening
manual/index.htmlviaQDesktopServices::openUrl, registered throughshortcut_registry.help_locatorshape.F1behavior is untouched.Editor tests run headless (
QT_QPA_PLATFORM=offscreen); test the resolver and the fallback decision, not the browser launch.4. Reference→guide bridge convention
A standard trailing section on reference pages linking the matching guide:
.qchviewer: an external-browser link into the packaged manual (QDesktopServices::openUrl), i.e. it must survivehelpc's link rewriting as an external URL rather than being rewritten to aqthelp://page or a GitHub blob URL. Decide the marker (a distinct URL scheme, an absolute URL, a generator-recognized section) and document it.Acceptance
F1.index.htmldirectly from the filesystem navigates correctly between pages and images.F1and the.qchpipeline are behaviorally unchanged.Out of scope — do not touch
versions.json, Amplify, any publishing workflow (docs-s3).docs-s4).docs-s1owns the structure.QWebEngineViewis rejected in ADR-0009; the external browser is the design.Epic: #344