Supported toolchain

ubCode and ubc were started as high-performance companion apps to efficiently develop and navigate Sphinx and Sphinx-Needs projects.

To achieve this, there are some focus areas:

  • Understand RST as docutils does, so it is 100% standards compliant

  • Understand what Sphinx adds on top, like directives, roles, domains and configuration

  • Support Sphinx-Needs specific directives, roles and configurations

The main goal is to ingest 100% of the primary data that Sphinx and Sphinx-Needs manage. Once that picture is complete, ubCode can provide a variety of features such as real-time indexing, previews, language server navigation, linting, formatting, schema validation, visualisations, MCP capabilities and much more.

A secondary goal is to improve the preview rendering so it becomes closer to how Sphinx renders HTML, but with outstanding performance. This means understanding more rendering-side features such as image embedding, Sphinx-Needs visualisations, rendering of certain directives and roles, etc.

This document describes which features of Sphinx and Sphinx-Needs are supported. If you stick to the features documented here, you can expect full support in ubCode and ubc. This will also have a positive impact on the qualification efforts of the overall toolchain at your organisation.

We will prioritise support for features that are widely used and requested by our users.

Configuration

ubCode and ubc require a declarative configuration style with TOML and JSON to fully understand Sphinx-Needs projects. Rationale:

  • Accessible outside of Python execution context (e.g., from Rust)

  • Reduces configuration complexity since the Sphinx configuration for large projects tends to become a whole software project on its own: many nested modules, 3rd party dependencies, long import time, dynamic code, etc.

  • Cacheable and fast-to-read configuration

  • Clear final state of configuration

Any configuration outside of this cannot be supported since ubCode and ubc do not execute any user Python code. There are efficient ways to deal with this by migrating your configuration or keeping the configuration in sync with what Sphinx/Sphinx-Needs would see at runtime. The new extension needs-config-writer might be worth a look.

Included features

Configuration

Directives

Roles

Data sources

  • sphinx-codelinks — source code tracing markers are ingested via the [codelinks] configuration section and the .. src-trace:: directive. See the codelinks guide for a walkthrough.

  • sphinx-test-reports — test results are ingested by converting the reports to a needs.json and importing it with needimport or [[needs.external_needs]]; see Test results from sphinx-test-reports. The [test_reports] section is read, and adds the need types and fields the converter’s output carries. The test-file, test-suite and test-case directives are supported, one need each, with the :auto_suites: / :auto_cases: expansion, and so are the test-results and test-env tables and the test-report directive (Test reports: the directives).

Upcoming features

  • needs_schema_definitions

  • A new form of dynamic functions that works for both Sphinx-Needs and ubCode/ubc. These functions will be limited in what they can do but will cover many use cases. More details will follow once this feature is designed.

  • Ingestion of other data sources:

    • Architecture data sources (concept work ongoing)

Excluded

Configuration

Dynamic conf.py configuration for Sphinx and Sphinx-Needs is not supported; see Configuration above.

Many of the configurations below are purely representational and do not impact the core data model of needs. More of these configurations will be supported in the future to improve the preview rendering.

Directives

What is excluded here is the Sphinx-Needs implementation of these directives, not necessarily their output: the view directives — needlist, needtable, needflow, needsequence, needpie, needbar and needgantt — are rendered by ubCode’s own engine, with the deliberate differences listed in differences. needgantt is the widest of those carve-outs: ubCode SOLVES the schedule itself and draws it as an inline SVG, where Sphinx-Needs generates @startgantt text for PlantUML — so :config: (a PlantUML snippet) and :scale: (raster sizing) are accepted and reported rather than applied, and the two need fields it measures from must be declared rather than invented. needextract is rendered by ubCode’s own engine as well, and as a view rather than a copy: the cards show the selected needs’ current metadata and their body, but no new need is created and none of the needs’ own anchors is repeated, so a link to a need always lands on the page that defines it. Several inputs that end a Sphinx build with a traceback — a footnote in the extracted content, a nested needtable or needextract, a mistyped id, and an argument together with :filter: — render or report a warning here instead. A sixth, needs_include_needs = False, has no equivalent to report: it is a conf.py setting, and conf.py is listed under Excluded above. Its :layout: and :style: options are applied to every card the site draws, ahead of the design and style each need resolves to for itself. See differences. needreport is rendered by ubCode’s own engine too, including its :template: surface: with no template it composes the same four sections a Sphinx build’s packaged template produces, and with one it renders that template against the same data a Sphinx build supplies. The differences page lists what diverges. needuml and needarch are rendered by ubCode’s own engine too, and this is the widest carve-out on the page: a Sphinx build renders the produced PlantUML into an image with a PlantUML server, and ubCode has none — it transpiles the diagram to Mermaid and the page draws it client-side. Everything upstream of that is the same: the body is Jinja, rendered against the same needs with the same callables (need, flow, filter, ref, uml and import), the same four-layer context precedence, and the same [needs] diagram_template. What follows from the transpile is that a construct Mermaid has no equivalent for is reported rather than drawn — add :debug: to see the PlantUML that was produced — and that :scale: sizes the diagram’s box rather than a raster. Several inputs that end a Sphinx build with a traceback report a warning here instead: a needarch outside a need, an :extra: pair whose value contains a colon, and a template error anywhere in the body. :save: is accepted and not yet written — the option is read and its path validated, but no .puml file is produced; needs_build_needumls, the whole-project dump, stays out for a different reason (an export is its own command in ubCode, not a build side effect). The differences page lists the rest.

list2need is implemented by ubCode’s own engine as well, and without the Sphinx-Needs limitations: each bullet becomes a real need, every one of them carries the source position of the item you wrote it on, and it works in a Markdown document, where a Sphinx build creates no needs at all. Its :presentation: option is read and reported rather than applied — see differences.

Five of the views below — needlist, needtable, needflow, needpie and needbar — additionally accept a ubCode-only :cypher: option, which selects needs by graph query rather than by field filter. Sphinx-Needs parses and ignores it on the first three from 8.4.0 onwards, and on both charts from 8.5.0 (sphinx-needs#1818); it documents that the option is ignored, and that on a chart the no-op changes a rendered number, so Selecting with Cypher is where the query language itself is taught.

On a chart the option is a scope — the universe each content-cell filter is counted in — rather than a selection, and both charts read that scope in a second, PORTABLE spelling too: :filter:, :status:, :tags: and :types:. :cypher: wins when both are written, which is what makes writing both the recommended form: ubCode evaluates the query and a Sphinx build scopes by the python surfaces, so the two engines show the same numbers wherever the scope has a python spelling — as far as the SCOPE goes: a chart’s counts cover needs only here and needs and their parts in a Sphinx build, so a project using parts still reads lower values (Needs chart views (needpie / needbar)). A bare :cypher: alone still diverges — a Sphinx build counts each cell over the whole project — and a link traversal has no python spelling at all (A chart’s filter options SCOPE its slices). Those four options are the chart’s scope in Sphinx-Needs from 8.5.0; on 8.4.0 and earlier they are unknown options there and the directive is dropped.

Roles