0.36.x

0.36.0

Released:

28.09.2026

The story of this release, in six arcs: a PDF you can shape — ubc build pdf (alpha) opens with a cover of your own and a table of contents, prints the running head and page number you write, takes its colours, type and typeface from your configuration, breaks pages where you say, turns wide tables landscape, typesets footnotes, citations, contents, needgantt and highlighted code, and draws emoji; one syntax highlighter for the site, the PDF and the preview — code is coloured once, by one engine from one language table — reStructuredText and MyST by ubCode’s own grammars — in a documented palette; typographic quotes, dashes and ellipses — prose is typeset as a Sphinx build typesets it, on the site, on paper and in the preview, by docutils’ own algorithm ported once ([build] smartquotes); anchors follow GitHub’s convention, and old deep links keep landing — HTML ids are spelled the way GitHub and MyST-Parser spell them ([parse] id_style), legacy_anchor_redirects forwards every anchor the change respelled, and a redirect may name a section; one element per name — a duplicated target, citation or footnote, an inline target, a need whose id a section would take, a heading with a cross-reference in it and a glossary term written as a role each resolve to one element everywhere; and the tools look after themselves — needflow and needsequence can be drawn by your PlantUML executable, .ub_cache cleans up after old versions and heals a damaged file, a licence check times out instead of hanging, Quality Analysis scores a need in one request, and the VS Code extension is on Open VSX. Twenty new warning-level codes ship on by default, several of which can fire on an unchanged project outside the PDF builder, and existing codes fire on new grounds too (see Breaking Changes).

✨ PDF build (alpha)

  • A table of contents, and a cover of your own. A PDF now opens with a table of its section headings down to three levels — dotted leader, page and link — on its own sheets after the title page; the body is still numbered from 1. [build.pdf.toc] sets depth and title or removes it with enabled = false, and --toc / --no-toc decide it for one run. [build.pdf.cover] adds a logo, a subtitle, an author and up to 16 lines of your own to the title page and switches any stock line off; --title-page / --no-title-page decide the cover for one run. See PDF document.

  • Colours, type and page furniture are yours to set. [build.pdf.theme.colors] repaints the document’s colour roles, each named after the site’s --ubc-* token without its prefix, and [build.pdf.theme.palette] names colours of your own for reuse as @name. [build.pdf.typography] sets every construct’s size (a factor of base_font_size) and face, can rule under headings and drop link underlines, and selects a typeface with font and font-mono from the files [build.pdf] fonts lists — the same list that supplies characters the built-in faces lack, such as CJK, or emoji beyond the bundled set. [build.pdf.header] and [build.pdf.footer] say what each margin prints, from {title}, {section}, {page}, {pages}, {project}, {version} and {date}. A font, family or logo that cannot be used is reported and the document still builds. See What each margin prints and How each construct is set.

  • Emoji are drawn, from a bundled set. A minimal monochrome set — 226 common emoji from Noto Emoji — is built in and draws, in the text and inside pictures, every emoji no other face covers. It comes last, after the built-in faces and every file [build.pdf] fonts lists, so a fuller or colour emoji font listed there draws every emoji it covers that the built-in text faces do not. An emoji outside the set is still omitted and reported as build.pdf_glyph_unavailable, now named as an emoji and pointed at a fuller font; [build.pdf] emoji = false takes the bundled set out, for a deliverable that must carry no emoji. See Emoji.

  • Page breaks you write, and landscape pages, in sphinx-simplepdf’s class names. The classes break-before, break-after and keep-together — through rst-class, :class:, a container or a MyST attribute block — start a block on a new page, start what follows it on one, or keep it on one page, and a block, container or section classed landscape is printed on turned pages (portrait turns back inside one). The names are those of sphinx-simplepdf, and its own dont-break, ssp-landscape and ssp-portrait are honoured as aliases, so a project written for that extension’s PDFs breaks and turns its pages the same way here. A .. raw:: latex block that is exactly one page-break command such as \newpage breaks a page too, and a table too wide for an upright page but not for a turned one — a needtable too — is printed landscape where it was a placeholder. Printing the site from a browser honours the same classes, and a class that cannot be honoured is reported. See Page breaks you write and Landscape pages.

  • Pages break more carefully, and [build.pdf.pagination] says where. A heading keeps three lines of what follows it, a split listing or table leaves two lines or rows on each side, a caption stays with its picture, an admonition title with its body and a line ending in a colon with what it introduces, and an empty document no longer prints a blank page. heading_keep_lines, orphans, widows and keep_introducers tune those rules, documents picks which documents start a new page, and break_before_level starts every heading of a level on one. Typesetting is also faster: each font face is looked up once per build and compression runs in parallel.

  • Footnotes and citations are typeset. A footnote’s note is set at the foot of the page its first mark falls on and runs on to the next page when it is long; every mark links to its note and the note links back. Citations gather on one Bibliography sheet at the end, with its own bookmark and contents entry, and each reference links to its entry. A .. rubric:: Footnotes above the definitions is left out, as Sphinx’s LaTeX builder leaves it out; a note too tall for any page foot is reported as build.pdf_note_oversized.

  • needgantt, contents and highlighted code are drawn; raw output is left out. A needgantt is a vector picture like needpie and needbar, every bar a link to its need’s card. The contents directive draws its listing of links, honouring :local: and :depth: as ubc build html does. Code blocks are coloured from the same grammars as the site, in the hl-* roles under [build.pdf.theme.colors], and :emphasize-lines: draws a tinted band rather than bold. A raw block or role, and HTML written directly in a Markdown document, is omitted with no placeholder and no finding, as Sphinx’s LaTeX builder omits it. See Charts are vector pictures and What is not rendered yet.

✨ Syntax highlighting

  • One highlighter for the site, the PDF and the preview. Code blocks, literalinclude, literal blocks and fenced blocks are coloured by ubc build html (alpha) during the build — pages no longer load a highlighting script — by ubc build pdf (alpha) on paper, and by the language server while it renders the preview; all three also colour an inline :code: role with a :language:. All three use one engine and one language table, so a construct gets the same colour everywhere, and the preview colours more than two hundred language names it left plain before. Languages lists every name. [build.highlight], or a builder’s own [build.html.highlight] / [build.pdf.highlight], turns it off with enabled = false and adds your own names with aliases = { mylang = "python" }; an unknown name is reported as build.highlight_language_unknown. See Code blocks are syntax highlighted and [build.html.highlight].

  • reStructuredText and MyST listings are coloured by ubCode’s own grammars. A .. code-block:: rst example is coloured from a grammar written from the docutils specification — directive names, arguments, option names and values, roles, targets, footnotes, substitutions and adornments — with a nested .. code-block:: body in the language it names; a myst listing colours a fenced block in the fence’s language and an {eval-rst} block as reStructuredText. See Code blocks.

  • A documented palette: nineteen classes, twenty-one colours. A highlighted run carries one of nineteen hl-* colour classes — plus hl-strong and hl-emphasis for weight and slant — painted from twenty-one --ubc-hl-* custom properties that are now part of the site’s stable theming surface; ubc build pdf uses the same names and default colours as its [build.pdf.theme.colors] hl-* roles. Every colour keeps the value the site already used, except --ubc-hl-link, which now colours URLs and hyperlink targets in markup listings.

✨ Smart quotes

  • Straight quotes, dashes and ellipses are typeset, as a Sphinx build typesets them. ubc build html and ubc build pdf (both alpha) and the editor preview educate prose with docutils’ own algorithm, ported once for reStructuredText and Markdown alike: "text" becomes “text”, it's it’s, -- an en dash, --- an em dash and ... an ellipsis — in paragraphs, titles (and so a page’s <title>, navigation and search entry, and the PDF’s cover, outline and running head), link text, captions, table cells and a need’s content. Inline literals, code, math and raw content, the literal roles, need titles and fields, needs.json and objects.inv are never changed, and a backslash keeps a character as written. [build] smartquotes = false turns it off, [build] smartquotes_action picks the replacements with Sphinx’s letters (default "qDe"), and the new [project] language chooses the quote characters — „…“ for "de", «…» for "fr" — and sets each page’s lang attribute. A Markdown parser that lists the MyST smartquotes or replacements extension is honoured, no longer reported as unimplemented. See [build] smartquotes and the differences from Sphinx.

  • A quote reads across inline markup, and an escape never turns a quote. Two of the registered differences from a Sphinx build: a quote beside emphasis, a reference or inline code sees the character on its other side, so ("*x*") shows (“x”) where Sphinx shows (”x”), and a line break counts as the space it renders as; an escaped character is kept as written and is, for the quotes beside it, the character it is, so ("\*args") shows (“*args”) where Sphinx shows (”*args”) for reStructuredText.

✨ Anchors and redirects

  • Moved sections keep their deep links (ubc build html, alpha). A [build.html.redirects] key may now name a section: "guide/setup#old-name" = "guide/setup#new-name", or = "guide/install" for a section that moved to another page. The reader’s browser forwards the link, a section still on the page always wins, and a page move combined with a section move takes one hop. An entry that cannot work is reported as build.redirect_anchor_unknown or build.redirect_anchor_shadowed.

  • Old deep links keep working after a change of id_style. [build.html] legacy_anchor_redirects = ["docutils"] forwards every anchor a page had under the "docutils" style and no longer carries — the anchors Sphinx makes, and the ones ubCode made before this release — to the anchor it has now, headings, positional id1 anchors, glossary terms, footnotes, citations and :name: anchors alike; ["github"] works the other way round. A hand-written redirect for the same anchor wins, and objects.inv and readers without JavaScript see the new anchors only. See legacy_anchor_redirects.

✨ Needs

  • needflow and needsequence can be drawn by your PlantUML executable (ubc build html and ubc build pdf, both alpha). Set needflow = true or needsequence = true in [build.plantuml], or in a builder’s own table, next to enabled = true; both are off by default, so an unchanged project draws as before and the editor preview keeps its Mermaid conversion. PlantUML lays the diagram out itself, as Sphinx-Needs does with needs_flow_engine = "plantuml", each needflow node links to its need, and in the PDF a real picture replaces the placeholder box. For needflow the new [needs] flow_engine key is the low-precedence default and a diagram’s own :engine: option wins, so a ubproject.toml shared with Sphinx-Needs that already says flow_engine = "plantuml" switches on upgrade wherever the executable is enabled. See External PlantUML renderer and, for what PlantUML cannot carry over, Needs flow diagram (needflow).

✨ Quality Analysis

  • A need is scored in one request, and an empty answer is never a score. Run QA now scores all of a need’s criteria in a single language-model request instead of one per criterion, so the need’s content is sent once and far fewer tokens are used; the new [quality.llm] batch_size splits the criteria into batches of that size, and batch_size = 1 restores one request per criterion. A response with no text is retried once on a freshly selected model, then twice more behind a not responding, retrying progress line, and only then reported as one error naming the ubcode.qualityAnalysis.llmselection setting; a response cut off before it scored every criterion gets its own message pointing at batch_size. See LLM hints.

✨ The VS Code extension

  • ubCode is on Open VSX. The extension is also published to the Open VSX Registry as useblocks.ubcode, so it installs from the Extensions view of Cursor, Kiro, VSCodium and other VS Code-based editors, pre-releases included.

👌 Improvements

  • .ub_cache looks after itself. The cache directory of another ubCode version is removed once that version has not used it for seven days, staging files left by an interrupted run are removed after a day, and writing the index cache holds its lock for a fraction of the time, so the language server and a concurrent CLI run wait less on each other.

  • A clean build does less work. ubc build html no longer runs the indexing lowering a second time for every page it renders: a clean build of the measured projects executes about a tenth fewer instructions (roughly 4–11 % less wall time with the default thread count), and ubc build pdf about 3.5 % fewer. Output is unchanged.

  • The bundled TLS library rustls is updated to 0.23.45 for RUSTSEC-2026-0285, which concerns the outbound HTTPS connections ubCode makes, such as licence activation, remote inventories and needs.json sources, and link checking.

‼️ Breaking Changes

  • HTML anchors follow GitHub’s heading-anchor convention by default. The new [parse] id_style key defaults to "github", so an anchor made from a title or a name may be spelled differently — headings, labels and targets, :name: and {#id} anchors, glossary terms, footnotes, citations, contents entries and math labels: Needs_Types 2.0 anchors at #needs_types-20 rather than #needs-types-2-0, a label keeps its underscores, a non-Latin title gets a readable anchor rather than #id1, and a repeated heading takes -1 rather than id1. A need’s anchor, which is its id, and object descriptions such as confval do not move. Cross-references, the tables of contents, search and your own objects.inv follow automatically, and a project consuming that objects.inv picks the new anchors up when it next refreshes its intersphinx cache; bookmarks and deep links copied by hand off a built page do not. To keep the previous, Sphinx-compatible anchors set [parse] id_style = "docutils"; to take the new anchors and keep the old deep links working set [build.html] legacy_anchor_redirects = ["docutils"]. See Parsing.

  • Some other anchors move. A heading that contains a cross-reference now keeps the reference’s text in its anchor (#about becomes #about-deep). A section, :name: or target whose anchor equalled the id of a need on the same page takes a de-duplicated anchor and the need keeps its id. An inline target that shared its slug with a section or another inline target gets an anchor of its own. A citation or a target name defined twice links to its first definition. A todo whose :name: has nothing to spell an anchor from takes an id1-style anchor, which shifts the todo-N anchors after it on that page. :ref:, :need: and objects.inv stay correct; a deep link copied by hand may need updating, and neither id_style = "docutils" nor legacy_anchor_redirects restores these — a section key in [build.html.redirects] forwards any single one.

  • [build.pdf] and [build.pdf.margins] refuse a key they do not know. A key that is not one of the table’s own names — a misspelt sub-table header such as [build.pdf.covr] included — is refused when the configuration is read, at the line it is written on, with the accepted names listed, and every command that reads the file stops, ubc check and the editor included. Until now it was ignored in silence. Remove the key, or move it to the table it belongs to: the common case is font, which belongs in [build.pdf.typography] while fonts stays in [build.pdf]. Every new [build.pdf.*] table refuses unknown keys the same way, except [build.pdf.theme.palette], whose keys are names you choose.

  • Built pages and PDFs change on upgrade: prose carries typographic quotes, dashes and ellipses. Every page and PDF of an unchanged project is re-rendered with its straight quotes, apostrophes, --, --- and ... educated (see Smart quotes above), titles included, so a site’s <title> elements, navigation and search entries change too; it moves no anchor, and objects.inv, needs.json and every need string stay as written. [build] smartquotes = false keeps every character as written, bar a MyST parser’s smartquotes or replacements extension; a smartquotes = False in a Sphinx project’s conf.py is not read, so set the key in ubproject.toml.

  • An unchanged project’s PDF comes out differently. It opens with a table of contents ([build.pdf.toc] enabled = false or --no-toc removes it); the page number reads n of N in muted ink ([build.pdf.footer] center = "{page}" restores the bare number); pages break under the keep rules above ([build.pdf.pagination] tunes them, heading_keep_lines = 1 and keep_introducers = false being nearest to before); code is coloured ([build.pdf.highlight] enabled = false turns that off) and :emphasize-lines: is a tinted band rather than bold; common emoji, omitted until now, are drawn ([build.pdf] emoji = false omits them again); prose carries typographic quotes, dashes and ellipses ([build] smartquotes = false, see above); a raw block no longer draws a placeholder or fails the build; a table too wide for an upright page but not for a turned one is printed landscape (class it portrait to keep the placeholder); and a cover that spills onto a second sheet no longer costs the body its page 1.

  • [quality.llm] max_tokens is retired. It never had an effect. The key still parses, so an existing ubproject.toml loads, but it is ignored and reported as the warning config.quality_max_tokens_retired, which fails ubc check and a default ubc build html run. Delete the key, or silence the code via [lint] ignore. [quality.llm] batch_size is the setting that shortens a response: fewer criteria per request, shorter answer.

  • A custom Quality Analysis prompt template must loop over criteria. The per-criterion variables criterion_id, criterion_name, criterion_description, scoring_guide and max_score are gone, because one prompt now scores several criteria: write {% for c in criteria %} and read c.id, c.name, c.description, c.scoring_guide and c.max_score. The built-in template needs no change.

  • Custom CSS for highlighted code must use the new hl-* names. Built pages no longer carry highlight.js’s .hljs-* classes or the data-ubc-highlighted attribute; a highlighted run carries one of nineteen hl-* colour classes instead. If your extra_css redeclared --ubc-hl-* properties: numbers, constants, operators and variables moved out of --ubc-hl-attr, labels out of --ubc-hl-built-in, escapes out of --ubc-hl-string, and --ubc-hl-title is now --ubc-hl-function, with the types it also covered under --ubc-hl-type. Default colours are unchanged. See Custom properties.

  • New warnings may appear on an unchanged project. On the default gate (deny = "warning") a warning fails ubc check and both builders. build.highlight_language_unknown fires in ubc build html and ubc build pdf wherever a code block, or an inline :code: role with a :language:, names a language the table does not know: correct the name, add it under [build.highlight] aliases, or use text. glossary.definition_as_term fires everywhere on a MyST {glossary} body line written as : definition, which is a term in ubCode and in Sphinx alike: indent the definition under its term. build.redirect_anchor_unknown fires in ubc build html for a [build.html.redirects] target whose #fragment names no anchor on its page, and config.quality_max_tokens_retired wherever that key is still set; config.invalid_smartquotes_action and config.smartquotes_unsupported_language only where the new keys name a letter or a language the educator does not know. Existing codes fire on new grounds too: std.ref for a :ref: to a target written directly above an external or indirect one, which passes its name on and owns no anchor, as in Sphinx (see A target stacked above an external target), and for a Markdown link spelled as an old positional #id3 anchor; std.duplicate_term for two glossary terms that now flatten to one name; and in ubc build pdf the build.pdf_* placeholder codes for a role, a formula or an image inside a parsed-literal or a link’s text, and build.need_view_failed for a :need_count: whose filter fails when it runs. Silence a code under [lint]: ignore = ["glossary.definition_as_term"]. The eight new build.pdf_* codes are reported only by ubc build pdf.

  • One-time full re-index and re-render on upgrade. The cache format moved (6.180 → 6.199) and the build manifest with it (112 → 131). The first run after upgrading rebuilds the index and re-renders every page once, about the cost of a cold build, then incremental behaviour resumes. Self-healing. Diagrams drawn by a configured PlantUML executable are rendered once more too, as their store lives in the same versioned cache. The link-check result cache and fetched intersphinx inventories are not discarded. The previous version’s cache directory is removed automatically once it has gone unused for seven days.

🐛 Fixes

  • One element per name, on every surface. A name claimed twice on a page — a directive :name: and a later label, two labels, two citations whose labels differ only in case — resolved to one element in :ref: and to another in a named reference or in objects.inv; every surface now names the first definition, and the ref.duplicate_target warning no longer fires for it. An inline target that took the id of a section or of another inline target gets an anchor of its own, also inside a table cell and inside content a needextract, needimport or needreport shows; a need keeps its id when an element on its page would take the same anchor; two MyST footnote definitions that differ only in case each keep an anchor; and a todolist entry links the todo it lists.

  • A cross-reference in a heading keeps its words. A heading such as Using :ref:`target` here lost the reference’s text wherever the heading became plain text: its anchor, its objects.inv row, the link text of a reference to it, search, the outline and glossary keys. It keeps the text now, as Sphinx does, and a Markdown page whose first heading is only a cross-reference gains a title. See Cross-references in titles.

  • A glossary term written as a role can be referenced. A term line written in backticks, or as a role such as abbr, registered nothing: a reference to it rendered as inert text with a std.term warning and objects.inv left it out. It links now, and intersphinx consumers reach it. A term defined twice in one file resolves everywhere to its last definition, as in Sphinx; go-to-definition and the project-level std.duplicate_term location follow.

  • Figure and image classes reach the page. A figure’s :figclass:, a figure’s or image’s :class: and a preceding .. rst-class:: were accepted and then dropped when the page was written. They now appear on the <figure> and <img> elements, in ubc build html and in the preview, and a class written twice is rendered once, as in Sphinx.

  • A link into a built page from another page lands in one step (ubc build html, alpha). Following page.html#anchor from another page showed the top of the page and then glided down to the target, because the site’s smooth scrolling also applied to the arrival; the glide now starts only once the page has loaded and been drawn, so an arrival lands directly while in-page jumps still glide. See Motion.

  • A damaged cache no longer fails every run. An unreadable index cache file made ubc check, ubc build, the language server and the MCP server fail on every run until .ub_cache was deleted; it is now discarded with a warning and rebuilt once. A cache directory emptied while the language server was indexing no longer leaves needs silently missing, and running ubc check or ubc build in a terminal on an unchanged project no longer empties the editor’s diagnostics view of its unresolved-reference and intersphinx findings until the next edit.

  • Licence checks no longer hang when the licence server is unreachable. With an online key, a check now gives up after about 20 seconds per request instead of blocking forever without output — in every ubc command, the language server and the MCP server — and explains the two ways out for a machine without Internet access: an offline activation file, or an HTTP CONNECT proxy (see Machines without Internet access). A proxy given as https://…, or a SOCKS proxy set for ubCode’s licence check, is now refused (the former sent the request unencrypted, the latter crashed): give it as host:port or http://host:port. The documented proxy variable is corrected to UBCODE_LICENSE_HTTPS_PROXY.

  • Positions inside an include that starts partway through its file name the right line. An .. include:: or {include} with :start-line: or :start-after: counted every position inside the included text from the start of the selected part. ubc check, the editor, every ubc build warning, go-to-definition, a need’s lineno and its __source__.line_range in needs.json now name the line the text is written on, a deliberate difference from docutils, which carries the same defect.

  • In a PDF, :emphasize-lines: counts the lines a block shows, from 1, as Sphinx and ubc build html do: without :linenos: nothing was emphasised, and with :lineno-start: the wrong rows were. A {#id} on a paragraph, list or block quote is now a link destination in the PDF, as it already was on the site, and a link to a label written just before a heading that opens a page lands on that page, not the page before it.

  • A PDF page no longer opens a line low, and a label at a document’s end stays with its document. When only the spacing after the block that filled a page did not fit — a picture fitted to the full height, a table at the foot, a document’s last block — the next page opened a gap below the top of the text area, and a .. _label: closing a document was set on the next document’s first page, so a link to it landed a page late. A paragraph’s, a listing’s or a document’s last lines are also no longer pushed onto the next page when they fitted and only the spacing after them did not, so some PDFs are a page or two shorter.

  • Vocalised Hebrew and Arabic no longer abort the PDF build. A letter with its points or marks, or an emoji sequence inside right-to-left text, stopped ubc build pdf with an error and no PDF; such text is drawn now. In the text layer that copy, search and screen readers get, a keycap or a letter with several combining marks no longer repeats its first character, and a pointed letter at the start of a line is no longer lost.

  • The missing-glyph finding names the character that is missing. build.pdf_glyph_unavailable charged a keycap, a flag, a skin-tone or a ZWJ sequence to its first codepoint — a keycap reported the digit the page does draw — and reported nothing for a character left out of the running header or footer, the table of contents or a list marker. It now names each missing codepoint, once per place it was left out.

  • A code block’s caption, a diagram’s caption and a link’s own text reach the paper. ubc build pdf dropped a code block’s :caption:, the caption of a diagram it drew as a box (every mermaid diagram, a needflow or needuml it could not draw) and a video’s, drew a Markdown link written with text, a button-ref’s content and a card’s :link-alt: as the target’s title, and left a :ref: to a named code block, needflow, math block, dropdown, line-block or toctree unresolved; all are drawn and linked now. A link whose text has no PDF rendering yet (an image, a formula) shows its placeholder and is reported.

  • Role values and parsed literals print as the site prints them. A :need_count:, :ndf: or :need_func: role printed its source where the site prints the value, and a count whose filter fails when it runs is now reported (build.need_view_failed), as on the site; a parsed-literal printed its markup, links, substitutions and escapes as typed, and now draws them line for line in its listing box; a directive the builder cannot render yet shows its argument and options in its placeholder box, as the site does. A role, a formula, a :download: or an image inside a parsed literal is now counted on its build.pdf_* warning, so a build at the default --deny warning can fail where it passed.

  • Text after an undrawn character stays in place, and a line is aligned by its true width. A character no font covers is still omitted and reported, but the text after it on the line was drawn shifted left by its width, opening a gap before the next font run; and a right-to-left paragraph, or a centred or right-aligned table cell, whose line held an emoji sequence or a ligature after a font change could be set a few points past or short of its margin.

  • An escaped backslash is kept, and a role’s content is unescaped once. In reStructuredText c\\d rendered as cd on the site, on paper and in the preview, and an escaped backslash at the end of a line swallowed the line break; a role’s content now follows docutils’ unescaping, so p\*q as the content of a :strong: role shows p*q, and C:\\Users --> Settings in :menuselection: shows C:\Users ‣ Settings, as in Sphinx.

  • Creating a need, and refreshing the Workflows and Overview panels, no longer wait ten seconds. A reindex of a project that was already current sent nothing for the extension to wait for, so the New need flow, a panel’s Refresh button, a ubproject.toml change and a successful agent action each sat out a 10-second timeout before going on; the language server now reports when every index pass has settled, changed or not.

  • A needgantt bar is painted in its palette colour on the site and in the editor preview where a slot bar with no completion, its done portion and a slot milestone were drawn in a neutral grey.

  • A needflow :config: takes its layout direction from the content of the named [needs.flow_configs] blocks, as Sphinx-Needs does, rather than from the block’s name, so a project-wide block carrying left to right direction draws that axis; an explicit :direction: still wins.

  • A link type’s style and style_end in [needs.links] default to Sphinx-Needs’ own values, "" and "->", where ubCode documented "solid" and ">"; copied into a ubproject.toml shared with a Sphinx-Needs build, the documented values made its PlantUML needflow draw -[solid]>, which PlantUML rejects. ubCode’s own diagrams draw exactly as before.