Conversation
Nothing reads it. poetry.lock locks the project, and upstream deleted uv.lock in June 2025.
Pygments knows no jsonc lexer, so Sphinx warned twice. Its JSON lexer accepts // and /* */ comments, and ubc has no lexer check.
The three developer notes are orphan: true, which both readers honour. The requirements traceability matrix joins the start page's toctree, because it is product documentation. Four 'not in any toctree' warnings go in each reader.
The ubConnect ReqIF export carries configuration, origin, priority and reqif_uuid, and the CSV import carries level. Undeclared, Sphinx warned and dropped them, and ubc dropped them without a warning.
clanguru documents declarations from system headers in the test listings, and their tabs raised 25 ubc warnings; the SPLed sources contain none. lint.per-file-ignores scopes the ignore to the listings until clanguru documents only the file's own declarations.
…anch only The runnable's SWIMPL_BC-003c sits outside any #ifdef, yet implemented SWDD_BC-203, which exists only with automatic brightness adjustment: a dead link in Sleep and IDEA/Sloemada. The link moves to a need inside the automatic branch. Upstream has the same modelling bug in the @rst block of SWIMPL_BC-003 (since b593419); this commit is kept separate so it can go upstream on its own.
sphinx-needs warns for an {if} block and sphinx-mounts for a rule, and both leave the content out. AGENTS.md said this happens silently.
A new use case for one-line implementation needs: where they live, how the component page shows them, and how #ifdef branches make a link hold only in some variants, with the compile database caveats. Two troubleshooting rows and a rule of thumb join it; use cases 17 and 18 become 18 and 19.
Move the ten `.. impl::` needs out of their `@rst`/`@endrst` blocks in light_controller, flight_controller, main_control_knob and power_signal_processing and into `// @need` one-line markers, matching the style brightness_controller already used. Titles, ids and the implements/fulfills links are unchanged. ubproject.toml replaces the per-component codelinks project with one shared `components` project rooted at `components/`; each component page traces its own source through it with a `src-trace` block. The source listings no longer define needs, so the integration suite's second listings stop duplicating them.
The shared codelinks project matches its include patterns below :directory:, so the block names the component's directory, not its src directory.
Need templates are Sphinx-only, so ubc showed the requirements without their images and with different content. The image is now part of the imported content, and the template, its option and the `image` field go.
Selecting a variant -- CMake configure, or tools/variant_data.py on its own -- now writes every file that decides what ubCode, ubc and the Sphinx build show, and nothing is maintained by hand per component: - ubproject.variants.toml, the document rules: one per component with a doc/index page, gated on membership of the variant's component list from parts.cmake, plus the scope rules of a per-component report. The same for every variant, at the project root because sphinx-mounts reads rule patterns relative to their file. - build/selection.toml, the selected build: its cell's variant data file and a mount of its build directory at `generated`, gated on the build's own variant and kit. It replaces the `generated` symlink or junction and build/autoconf.json. - <build>/selection/[<component>/]<shape>.toml, the same for every documentation run spl-core starts (SPL_SPHINX_OPTIONS), so the reports of two builds can be built side by side; a component report's file also names its root document. - component cells, build/variants/<V>/<kit>/<component>/<target>.json, with build_config.scope and build_config.component, so ubCode builds a per-component report from the same files. ubproject.toml extends the rules file, which extends the selection. conf.py hands the selection's keys to sphinx-needs and sphinx-mounts, which read one TOML file each and do not follow `extend`, and stops with a clear error when nothing is selected. The components page globs every component's documentation.
SPL_TEST_RESULTS_AS_NEEDS: spl-core writes each component's test results as needs.json after the test run, and the results page imports it, with the test specifications' `results` links as needextend blocks. ubproject.toml declares the three types and their 14 fields, because no extension registers them any more; conf.py loads neither sphinx-test-reports nor the sple_tr_link needs function, which removes two configuration warnings. The `file` field has to be declared, because ubc drops an undeclared field of an imported need without a word. sphinx-codelinks registers a field of the same name, and sphinx-needs compares names only, so conf.py filters exactly that one warning.
codelinks takes each variant's #ifdef branches from build/compile_commands.json, which only VS Code's CMake Tools used to write, and only when configuring there. tools/compile_commands.py copies the selected build's database there on every build and for every documentation run, without the test kit's -save-temps, with which libclang cannot load a file: codelinks skipped the file and its needs disappeared. The IDE's own copy goes, because it would bring the option back.
Each component's Verification toctree names its source listings as well, and the two example components, which have tests but had no Verification section, get one. spl-core's wrapper pages were the only route to the listings, and SPLed links no wrapper: Sphinx reported the wrappers and ubCode the listings as in no toctree. The wrappers stay out of both readers now, because the mount admits only the report pages and listings.
AGENTS.md and VARIANTS.md describe what the selection step generates and how each reader takes it: the rules file, the selection and the per-run files, the component reports, the one-line needs and the compile database, the test results as needs, and the one gap left, ubCode not mounting a directory inside the project. Adding a component is adding it to parts.cmake and writing its documentation; hand-written special-case rules go into doc/variant_rules.toml.
For every variant and kit, test_docs_gate.py configures the cell's build (nothing is compiled), builds the documents with sphinx-build -W and with ubc, and compares the two needs.json files need by need. What the readers may differ in is named, with its reason, in docs_exceptions.toml: today REQ_37 and REQ_58, the untitled needs of the upstream export, and ubc's two warnings about them. Both build times go into the job summary. The documentation job installs Ninja and has the time to configure the cells.
useblocks/spl-core feat/docs-parity-sweep at 1181c0a adds SPL_SPHINX_OPTIONS and SPL_SPHINX_COMPONENT_OPTIONS (each run names its own selection file), lets the binary directory check pass for a mounted path, and writes the test results as needs (SPL_TEST_RESULTS_AS_NEEDS) with its JUnit converter.
tools/config_checks.py holds the checks the tests ran: the vendored needs model against spl-core's, ubCode's parser includes against conf.py's include_patterns, what ubproject.toml must leave to the generated files, and the generated rules against the grammar both engines share. conf.py runs them at config-inited and reports each finding as a warning, so a drift fails the build under -W instead of waiting for someone to run the tests.
The configuration tests read the generated rules and evaluate them, and the scope rules of a component report, with sphinx-mounts' own interpreter against the real cells; they check the one extend chain, the mount's condition and conf.py's source set by executing conf.py, and run the checks conf.py runs. The generator tests cover the component cells, the selection files with and without a build and for a component report, removing what earlier versions left, and hand-written rules. The documentation tests build through a selection file that mounts a fake build, where they used to re-point the link; ubCode reports a glob of the component toctree once, so the ubc comparison is made per glob.
ubc refuses an image in imported need content unless the import source is listed under [[needs.import_sources]] with allow_assets; since the image moved into the content, that is the CSV import. Sphinx needs no such permission and ignores the key.
sphinx-codelinks does not find the git root where .git is a file, and warns once per source (codelinks.git_ref). The gate tolerates exactly that warning, and only in a linked worktree; a clone, as on CI, has no such warning.
Two things let every component into a per-component report. A rule pattern without a slash matches at every depth, so the variant-wide rule's index.md also removed the component's own doc/index.md: the root index is no longer named, and is an orphan page, whose toctree entries a component report excludes anyway. And both readers match a rule's patterns against a mount's files relative to the mounted directory, so generated/<component>/** never narrowed the mounted build: each component's rule now names <component>/**, which covers its documentation in the tree and its pages in the build alike, and the variant's own pages are reports/**.\n\nA component report's links to the rest of the product dangle by design. Its selection file says so in ubc's terms (lint.ignore needs.dead_link), and conf.py suppresses sphinx-needs' needs.link_outgoing for that report. The rule tests now decide real paths with sphinx-mounts' own matcher, instead of comparing pattern strings, which is what let this through.
Every component report spl-core builds, in the docs shape, in both readers, strictly, with the needs compared: 24 of them next to the 10 variant cells. Each run selects its cell first, because codelinks reads the selected build's compile database.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #3. Makes Sphinx and ubc read the same documents and needs for every variant, following the reviewed issue list (numbers below). Commits are kept per issue, so each can go upstream on its own; the spl-core side is useblocks/spl-core#5.
What changes for a user
tools/variant_data.pyon its own, writes the variant data, the document rules (ubproject.variants.toml, one per component, derived from where its documentation lives), and the selection (build/selection.toml: the cell's variant data file and a mount of the build directory atgenerated). Nothing per component is maintained by hand: adding one is adding it toparts.cmakeand writing its documentation.generatedlink, no junction, nobuild/autoconf.json. Each build keeps its pages in its own directory, and every documentation run spl-core starts names its own selection file, so the reports of two builds can be built side by side, andubc diff -c "$(cat build/<V>/<kit>/<type>/selection/reports.toml)"compares builds.scope = "component"), scope rules, and the report's root document in its selection file.@needcomments shown on each component's page; codelinks takes each variant's#ifdefbranches from the selected build's compile database, copied without the-save-tempslibclang rejects.sple_tr_linkneeds function are gone.Commits, by issue
feat: select a variant with generated files instead of a link,fix: show only its own component in a component reportfeat: import the test results as needs in both readers(with the converter in spl-core#5)refactor: define implementation needs as one-line commentsdocs: give every generated page a place in the navigationdocs: give every page a place in the navigationdocs: highlight the JSON blocks with comments as jsonfeat(needs): declare the fields the imported needs carryfeat: hand codelinks the selected build's compile databasefix(brightness_controller): implement SWDD_BC-203 in the automatic branch only(upstream has the same bug)chore(ubc): ignore tabs in the generated source listingsfeat: check the configuration whenever Sphinx reads itci: gate the documentation on both readers, strictly,ci: gate the per-component reports as well,fix(csv): put the requirement images into the needs' content,fix(csv): let ubc show the images of the imported requirementschore: drop uv.lockdocs(agents): a condition that cannot be evaluated warnsdocs: describe the generated selection, VARIANTS.md use case 17, tests, the spl-core pinChecked locally
test/test_docs_gate.py, the new CI gate: 34 of 34 — all 10 variant cells and all 24 per-component reports, each configured (nothing compiled), built bysphinx-build -Wand by ubc, with the two needs.json files identical apart from the named exceptions (REQ_37,REQ_58, untitled in the upstream export). ubc builds a cell in 0.2–0.3 s, Sphinx in 1.5–2.5 s.test_ubproject_config.pyandtest_variant_data.py: 96 passed.test_documentation.py -m docs: 31 passed, 1 skipped (the CI-only ubc requirement).reports: 3 warnings left, all sphinx-codelinks not finding the git root in a linked worktree (a clone, as on CI, has none).Known gap
ubCode does not mount a directory that lies inside the project root, and every build lives under
build/: ubc and the IDE read the documents, the rules and the implementation needs of every variant, but no generated page (test results, test specifications, listings) — 92 of Sphinx's 134 needs in the Discoreportsbuild, every shared one identical. Sphinx reads them. Closing it needs that ubCode change.Not in this PR
{if}blocks around report sections) and 20 (the untitled imports) are out of this sweep.