V2.0 — Shipped (tag v2.0.0, 2026-08-11)
:::info The only bucket with a checkable 100%-done claim
Everything in this file is delivered in the tagged v2.0.0 release — the project's first-ever GitHub
Release, published 2026-08-11. The full execution ledger (492/492 items closed) is
.antigravitycli/v20_todo.md; this file is the published, requirement-shaped summary of that ledger,
not a duplicate of it — for execution history (dates, commits, individual task closures) follow the
links below into v20_todo.md rather than expecting that detail here.
Requirement ids below are promoted, unedited in substance, from .antigravitycli/requirements_v3_next.md's
internal REQ-V2-01..REQ-V2-10 numbering (that file's own banner explains the _next filename refers
to the next unshipped release, v3.0 — its content, despite the name, is the historical v2.0 record).
Each entry keeps its GAP-NN alias permanently, since v20_todo.md and the TASK-<phase>.<group>.<seq>
mappings cite by GAP-NN, not by the REQ-V2-* id.
:::
Cluster A — Infrastructure
REQ-V2-01
Global Config Field Activation
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-09 - Traces to:
REQ-BUS-12 - Evidence:
.antigravitycli/v20_todo.mdcloseout ledger; not independently re-verified againstengine/ude/config.pyin this pass — flagged for a follow-up spot-check. - History: v1.0 had only
error_policyactive; v2.0 activates all documentedGlobalConfigfields.
All fields in ude_global_config.json (doxygen_path, log_level, log_file, cache_root_dir,
global_templates_dir, error_policy) are read, validated via a Pydantic GlobalConfig model, and
operationally applied at engine startup. Unknown keys are silently ignored
(ConfigDict(extra="ignore")); missing fields default without raising ValidationError.
translation_service stays reserved — correctly: it is a v4.0+ dependency (see REQ-BUS-06 in
v4.0-backlog.md), not an oversight.
REQ-V2-02
Unified Logging Infrastructure
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-12 - Traces to:
REQ-BUS-09 - Evidence:
.antigravitycli/v20_todo.mdcloseout ledger; not independently re-verified againstengine/ude/in this pass. - History: supersedes
REQ-FUN-25's v1.0 baseline logging in scope (v1.0 entry preserved for traceability inv1.0-mvp.md).
A single scoped "ude" root logger is configured via logging_setup(cfg: GlobalConfig) at startup,
supporting StreamHandler (always) and optional FileHandler (when log_file is set). The incorrect
logger label "ude.renderers" in interfaces.py is corrected to "ude.interfaces". Calling
logging_setup() twice does not accumulate handlers.
REQ-V2-03
L2 Render Cache Activation
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-07 - Traces to:
REQ-BUS-03,REQ-BUS-09 - Evidence:
engine/ude/storage.py(BuildCacheManager, existed since v1.0); wiring into all 16 rendererrender()calls per.antigravitycli/v20_todo.mdcloseout — not independently re-verified against every renderer class in this pass. - History: activates the L2 cache described in
v1.0-mvp.md's baseline form.
BuildCacheManager's L2 cache is wired into all 16 concrete renderer render() calls, keyed on the IR
hash plus the Jinja2 template hash. The orchestrator passes cache_dir (from GlobalConfig.cache_root_dir) via a
cache_manager kwarg forwarded through the __new__ factory in all three renderer families
(static_html, hugo_markdown, the ODA family). When cache_root_dir is absent, behavior is identical
to v1.0 — no regression.
REQ-V2-04
Doxyfile 3-Tier Key-Level Merge
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-11 - Traces to:
REQ-BUS-13 - Evidence:
engine/ude/collectors/doxyfile.py; key wiring inengine/ude/collectors/doxygen.py(verified::642-657implements the relatedexclude/exclude_patterns/file_patternsruntime keys, part of the same T3 runtime tier this item's key-level merge governs — seeREQ-V3-09for the filtering-specific requirement this evidence primarily supports). - History: replaces
v1.0-mvp.md's source-concatenation approach.
Doxyfile assembly uses an explicit 3-tier key-level merge (T1 global template → T2 target-specific
template → T3 runtime parameters), with T3 always winning and key conflicts logged at DEBUG. Existing
ude_doc_config.json files using doxyfile_template continue to work identically.
Cluster B — Library API & CLI Unification
REQ-V2-05
UdeOrchestrator Public Library API
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-05 - Traces to:
REQ-BUS-09 - Evidence:
engine/ude/orchestrator.py:77(find_product_json),:99(deep_merge) — verified: both utilities now live inorchestrator.py, consistent with this requirement's consolidation goal (not independently confirmed thatcli.pyno longer duplicates them).
UdeOrchestrator exposes stable public methods parse(config, config_dir),
render(catalog, config, config_dir, out_dir), and run(doc_config_path). The previously duplicated
deep_merge()/find_product_json() utilities are consolidated into orchestrator.py; cli.py is
reduced to argument parsing plus a thin orchestrator delegation.
REQ-V2-06
CLI Subcommands
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-01 - Traces to:
REQ-BUS-09 - Evidence:
engine/ude/cli.py. - History: landed 2026-07-19, ahead of the rest of the v2.0 cluster (per
v1.0-mvp.md, the v1.0-era flat invocationude --global-config <path> --sdk-config <path> --doc-config <path>remains supported as a backward-compatible alias).
The CLI supports four subcommands (compile, parse, render, audit) via argparse subparsers. The
v1.0 flat flag interface remains fully operational. ude parse --output-ir followed by
ude render --input-ir produces byte-identical output to ude compile.
Cluster C — Typed Intermediate Representation
REQ-V2-07
7-Model Typed Entity Schema
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-03 - Traces to:
REQ-BUS-01 - Evidence:
engine/ude/models.py. - History: replaces
v1.0-mvp.md'sClassEntitydiscriminated union. Prerequisite forREQ-V2-08.
The v1.0 ClassEntity discriminated union is replaced with seven explicit Pydantic models:
ClassModel, MethodModel, ParameterModel, EnumModel, VariableModel, ConstantModel,
TypeAliasModel — all carrying model_config = ConfigDict(extra="ignore") for forward compatibility.
Backward-compatible aliases (ClassEntity = ClassModel, etc.) ship in the same commit.
fields: List[str] becomes fields: List[VariableModel]. Old v1.0 .json.gz IR files deserialize
without ValidationError.
Cluster D — QA & Testing Completeness
REQ-V2-08
Documentation Coverage Gate
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-10 - Traces to:
REQ-BUS-08 - Evidence:
engine/ude/coverage.py;.antigravitycli/v20_todo.mdFIN-9.13— real command run,ude.cli audit --mode reject-undocumented --threshold 98, exit 0, 100.00% coverage, 351 entities.
Two enforcement modes are configurable via GlobalConfig: reject-undocumented (non-zero exit if
coverage is below coverage_threshold) and allow-undocumented (warnings only, exit 0). ude audit
prints a per-entity-type Markdown coverage table. No LLM calls occur in v2.0 — the enrichment modes
(auto-document, verify-document) are v4.0+ scope, see v4.0-backlog.md. The
coverage gate runs during ude compile and ude audit, not during ude parse/ude render.
:::note Three v1.0-era requirements folded into this delivery, with a narrower scope than originally specified Found during this restructuring — none of the three had a home in any prior draft of this catalog:
REQ-FUN-12(Standalone Coverage Reporting Command) is substantially satisfied:ude auditis exactly the independent, standalone coverage subcommand this requirement asked for (under a different name than theude coveragethe original text proposed).REQ-FUN-15(Quality Gate Scope & Completeness Criteria) is only partially satisfied. Verified againstengine/ude/coverage.py:180-193(_record/compute_coverage): an entity counts as "documented" ifdocstring is not None— a shallow presence check. The full criterion this requirement specifies — every parameter and the return value must independently carry a non-empty description — is not implemented; nor are enums, constants, or type aliases counted yet (noted in the function's own docstring). This gap is real, outstanding V3.0 work — seeREQ-V3-13inv3.0-next.md.REQ-FUN-16(Quality Gate Automatic Exclusions) is not implemented as specified. Verified againstengine/ude/coverage.py:56(_is_excluded_from_coverage): exclusion is purely name-pattern based (private_foo, dunder__foo__,logger, and a small hardcoded false-positive list — seeuser-docs/docs/exclusion-gates.md's coverage-gate section). There is no semantic exclusion of trivial property getters/setters or of methods inherited unchanged from a base class/stdlib (Equals/GetHashCode/ToString,__str__/__repr__) — agrepfor those names incoverage.pyfound nothing. This is real, outstanding V3.0 work — folded intoREQ-V3-13. :::
REQ-V2-09
External Integration Script Confirmation
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-31; coversTEST-INT-01(run_regression_tests.py),TEST-INT-03(verify_pages.py),TEST-INT-04andTEST-INT-06(check_links.py) — those four ids keep their full specifications insrs/integration_tests_specification.md(retained, not retired) - Traces to:
REQ-BUS-08 - Evidence:
tests/integration/regression/{run_regression_tests.py,verify_pages.py,check_links.py}; full resolution history and path-migration corrections in.antigravitycli/requirements_v3_next.md'sREQ-V2-09section.
The three integration scripts originally referenced under a Tests/ path (run_regression_tests.py,
verify_pages.py, check_links.py) are located at their current canonical path,
tests/integration/regression/. The run_all_integration_tests.{sh,bat} aggregator script itself is
orphaned (positional-arg calling convention no longer matches the scripts' real CLIs, and it is
referenced by zero CI workflows) — resolved not by resurrecting it but via its actual working
successors: per-repo check_links.py inside each deploy.yml, and verify_pages.py --remote-url
inside integration_tests.yml's scheduled verify-live-pages job, both confirmed passing against live
sites.
REQ-V2-10
Per-Language Integration Test Suites
- Status:
PARTIAL— suites are delivered; four per-language rendering residuals are reassigned to V3.0, see below - Target:
v2.0 - Alias:
GAP-32 - Traces to:
REQ-BUS-08 - Evidence:
engine/tests/per-language integration suites (file-level; individual test files not enumerated in this pass).
Full parse → render integration test suites are implemented for all four supported languages, covering
entity types not exercised by the golden-master regression suite, via a shared LanguageIntegrationBase
mixin. What this delivered is test-suite existence and coverage of already-shipped behavior — it did
not deliver new rendering features. Four residual per-language rendering gaps identified during this
work are not closed by this requirement and are reassigned as V3.0 scope, folded into
REQ-V3-01/REQ-V3-04 in v3.0-next.md because they are the same underlying work as
GAP-28 (structural render parity): C++ category landing pages, C# interface/delegate/event rendering,
Java extends/implements relationship rendering, and (kept separate, since Python already has partial
support) Python fget/fset property and dunder-method edge cases.
:::note Classification note
This entry (and REQ-V2-09) are catalogued as functional deliverables, not non-functional: "a test
suite exists and covers X" is a functional deliverable. Only coverage thresholds and pipeline
resilience properties belong in nfr.md's Operability category.
:::
Pulled forward from the original v3.0 scope
REQ-FUN-50 (v2 form)
sidebar.toml as Mandatory Single Navigation Source
- Status:
IMPLEMENTED - Target:
v2.0 - Alias:
GAP-06 - Traces to:
REQ-BUS-10 - Evidence:
engine/ude/renderers/static_html.py:526-535— verified:HtmlRendererraisesRendererErrorwhensidebar_confighas no[[sidebar]]entries, with an inline comment ([IMP-32.10]) explicitly stating "there is deliberately no default navigation fallback here." - History: see
v1.0-mvp.mdfor the v1.0 per-renderer-class JSON mechanism this replaces.
The per-renderer-class toc_<Class>.json files are removed entirely; navigation is sourced from a
single sidebar.toml per project (not per renderer class). The file is mandatory — missing,
malformed, or empty (sidebar = [], or zero [[sidebar]] entries) all raise UdeException/RendererError;
there is no default navigation at any tier. Resolution follows a 3-way deep-merge cascade (global → SDK
→ document). The [groups] folder-taxonomy table is the one exception that keeps an engine-tier
default, described under v1.0-mvp.md.
REQ-V2-11
Static / Inline / Redirect Page Node Rendering
- Status:
IMPLEMENTED— flat nodes only, see the boundary note below - Target:
v2.0 - Alias:
GAP-26 - Traces to:
REQ-BUS-10,REQ-BUS-11 - Evidence:
engine/ude/renderers/static_html.py:559-588(verified:elif item_type in ("static", "inline")at:559,elif item_type == "redirect"at:571, each hard-coding"children": []on its nav-tree node —:569,:584,:587);engine/ude/renderers/hugo_markdown.py:515-554(verified:elif item_type in ("static", "inline", "redirect")at:515, same per-type handling); test coverageengine/tests/test_static_pages.py(not independently re-read this pass).
sidebar.toml root-level static, inline, and redirect node types render correctly in both
renderer families. static nodes extract <body> content from an HTML source file or all content
(minus front-matter) from a Markdown source file; inline nodes embed content directly in
sidebar.toml; redirect nodes emit a meta-refresh/JS redirect (Hugo) or an external_link nav entry
(standalone HTML) depending on whether content is present. Both engines support Jinja2 variable
interpolation in static/inline content.
:::caution Boundary — this is exactly where GAP-30 begins
Every node rendered by this requirement is flat. static_html.py's sidebar loop (:539-588)
iterates sidebar_items at the top level only and hard-codes "children": [] on every custom-page
node it creates. hugo_markdown.py's only other children-shaped structure (:588-602,
_build_child_namespace_map) is the unrelated namespace-nesting map, not sidebar-item children. Neither
renderer recurses into a static/inline/redirect node's own children array — confirmed by
grepping both files for item.get("children")/item["children"]: no matches. Nested composition of
these node types is REQ-V3-02 (GAP-30), not this requirement. Do not cite this requirement's
delivery as evidence that GAP-30 is done — see v3.0-next.md.
:::
Content-alignment achievement (do not conflate with GAP-28)
REQ-FUN-49 (v2 scope)
Docomatic Semantic Alignment at Scale
- Status:
IMPLEMENTED - Target:
v2.0 - Traces to:
REQ-BUS-08,REQ-BUS-10 - Evidence:
ude_docomatic_coverage.md,ude_docomatic_alignment_rules.md(rules 1–22);engine/tests/test_docomatic_alignment.py:490-494,694-701— verified:MAX_ALLOWED_DIFFERENCES = {"cpp": 906, "csharp": 241, "java": 392}, and the ODA-renderer-family parametrization gatesoda_htmlfor cpp/cs/java plusoda_hugo_markdownfor cpp. - History: extends
v1.0-mvp.md's baseline harness to full production scale.
:::info Post-freeze correction (2026-08-21) — evidence path moved, achievement unchanged
The cited engine/tests/test_docomatic_alignment.py no longer exists at that path: DEL-A04
(Clean Room extraction) relocated oda.py and its alignment test/baseline to flude-oda-plugin
(now flude-oda-plugin/tests/test_docomatic_alignment.py), a separate repository. This requirement's
39-combination/16-SDK achievement itself is unaffected and remains real — only its evidence now lives
in a different, ODA-plugin-specific repository, consistent with flude-oda-plugin being the sole
legitimate place for comparison against real ODA/Doc-O-Matic output going forward (see REQ-V3-44).
engine itself retains an orphaned, now-unused tests/assets/golden_master/html_oda/ fixture
directory from before this move — dead weight, not a functional dependency (confirmed:
PIPELINE_COMPLEXES in engine/tests/test_golden_master.py has no oda mode referencing it).
:::
Docomatic semantic alignment achieved across 39 combinations / 16 SDKs: every residual missing/extra
difference is either a shipped fix, a documented rule (ude_docomatic_alignment_rules.md, rules 1–22),
or individually verified as real content Docomatic does not itself document.
:::danger Anti-pattern to avoid citing
.antigravitycli/planned.md:198 cites this requirement's "≥98% Docomatic match" as evidence that
GAP-28 (structural render parity) is done. These are different properties. REQ-FUN-49 measures
text/content alignment via an allowances engine that tolerates known structural differences; GAP-28
measures whether a renderer emits the same set of pages at all. Verified this pass:
static_html.py's HtmlRenderer._post_render (:232, no-op body at :240) and oda.py's
ODAHtmlRenderer._post_render (:290, no-op body at :298) are both no-ops on the base class shared
by the C++/C#/Java subclasses; only the Python subclasses override it (static_html.py:928,
oda.py:921). The ≥98% figure belongs here, at REQ-FUN-49, and must never be used as evidence for
GAP-28 — see v3.0-next.md.
:::