| 1 | <!-- English translation of adr/0018-ide-commands-canonical-xml-documentation.md. Canonical Russian: ../../adr/0018-ide-commands-canonical-xml-documentation.md --> |
| 2 | |
| 3 | # ADR 0018: Canonical XML docs for `IdeCommands` and ProtocolDocGen |
| 4 | |
| 5 | **Status:** Accepted (partially: ProtocolDocGen + generated summaries; full XML on IdeCommands - on migration) |
| 6 | **Date:** 2026-04-05 |
| 7 | ## Related ADRs |
| 8 | |
| 9 | | ADR | Role | |
| 10 | |-----|------| |
| 11 | | [0013](0013-command-surface-and-discoverability.md) | single registry `command_id` | |
| 12 | | [0008](0008-mcp-contracts-and-testable-infrastructure.md) | MCP contracts | |
| 13 | |
| 14 | ### Outside ADR |
| 15 | |
| 16 | | Document | Role | |
| 17 | |----------|------| |
| 18 | | [ide-commands-protocol-docgen-contract.md](../dev/ide-commands-protocol-docgen-contract.md) | current parser contract | |
| 19 | |
| 20 | --- |
| 21 | ## Context |
| 22 | |
| 23 | The command registry **`IdeCommands`** (partial class, `Services/IdeCommands.cs` + `Services/IdeCommands.*.cs`) is supplied with XML comments; **`tools/CascadeIDE.ProtocolDocGen`** generates `IdeCommandsDoc`, `IdeCommandsArgs`, `IdeCommandsContract`, **`MCP-PROTOCOL.md`** fragment and lints the contract. |
| 24 | |
| 25 | Currently, the machine-readable parts of the contract (**`returns:`**, **`args:`**, **`example:`**) are nested **in the text `<summary>`** - see [ide-commands-protocol-docgen-contract.md](../dev/ide-commands-protocol-docgen-contract.md). This simplified the first line parser, but: |
| 26 | |
| 27 | - for **an open repository and new contributors** the **standard** structure of C# XML documentation (`<summary>`, `<param>`, `<returns>`, `<example>` / `<code>`) is more common; |
| 28 | - **IDE** and familiar tools expect a human description in the summary, and a return type and parameters in the designated tags. |
| 29 | |
| 30 | ## Solution (target state) |
| 31 | |
| 32 | **Basic idea:** rely on **familiar** tags (`<summary>`, if necessary `<param>` / `<returns>` for a person), and express the **machine contract** for ProtocolDocGen **separately** - either inside standard tags by agreement, or through **your own (extended) XML tags**, without replacing the base ones with them. |
| 33 | |
| 34 | ### Option A - standard tags + conventions only |
| 35 | |
| 36 | 1. **`<summary>`** - brief description for the person; machine parts if necessary in **`<returns>`** and **`<param>`** by explicit rules (see option B below for mixing). |
| 37 | |
| 38 | 2. **`<param name="…">`** - human-readable description; for the `IdeCommandsArgs` scheme - **convention** (the first line is the `name:type` mini-grammar, the rest is text) **or** one line of the scheme in **`<remarks>`**. |
| 39 | |
| 40 | 3. **`<example>`** + **`<code language="json">`** - example for linting. |
| 41 | |
| 42 | ### Option B - standard tags + **custom** tags (preferably discussed) |
| 43 | |
| 44 | Do not “break” the semantics of standard tags with a hard machine string, but **add** elements with **fixed names** under Cascade/ProtocolDocGen, for example (fix the names at the Accepted stage in the dev-doc): |
| 45 | |
| 46 | - a separate tag for **argument schema** (one line in the old grammar or structured XML inside); |
| 47 | - a separate tag for the **return type** of the contract (`json` / `text` / `none`); |
| 48 | - if necessary, a separate tag for **JSON example** (if you don’t want to duplicate the logic with `<example>`). |
| 49 | |
| 50 | **Why this is natural:** the C# compiler **preserves** non-standard tags in the output XML documentation; **IDE** by default shows in Quick Info mainly `<summary>` / `<param>` / `<returns>` - custom tags do not “break” tooltips, and **ProtocolDocGen** reads the full block and extracts both standard and custom elements. Many **SDKs and dock generators** do this (Sandcastle/DocFX have their own tags; the project has its own controlled set). |
| 51 | |
| 52 | **Tag names:** It is better to have a **stable prefix** or a namespace-like scheme (`cascadeArgs`, `cascadeReturns` - or one consistent block name) so as not to interfere with future tool extensions. |
| 53 | |
| 54 | ### Common to both options |
| 55 | |
| 56 | 4. **Parser implementation:** parsing **XML document to symbol** (preferably **Roslyn** + full XML comment to `const`); gluing `IdeCommands*.cs` as it is now. |
| 57 | |
| 58 | 5. **Migration:** translate `IdeCommands.*.cs` to the selected template; if necessary, a short **compatibility** lint with the old format in `<summary>` or one major commit. |
| 59 | |
| 60 | ### Select A vs B |
| 61 | |
| 62 | Leave for ADR finalization: if **B** - there are fewer compromises in the wording of standard tags and the “man/machine” boundary is clearer; price - **document the list of custom tags** and embed them into the parser once. |
| 63 | |
| 64 | ## Consequences |
| 65 | - **Pros:** closer to the C# ecosystem, easier onboarding; **option B** further separates "prose for people" from "fields for generator" without layering grammar on `<summary>`. |
| 66 | - **Disadvantages:** one-time **cost** of refactoring the parser and comments; for **A** - strict convention on the text inside `<param>` / `remarks`; for **B** - **catalog of custom tags** and support in ProtocolDocGen (but the contract is explicit). |
| 67 | - **Documentation:** update [ide-commands-protocol-docgen-contract.md](../dev/ide-commands-protocol-docgen-contract.md) after accepting the implementation (or in the same PR as the parser). |
| 68 | |
| 69 | ## Rejected alternatives |
| 70 | |
| 71 | - **Keep only the minilanguage in `<summary>` forever** - rejected as a long-term goal for an open repository: works, but worse for contributors and standard expectations. |
| 72 | |
| 73 | ## Status |
| 74 | |
| 75 | Before switching to **Accepted** - after choosing **option A or B**, exact tag names (including custom ones), agreement on args and parser implementation (and, if desired, a pilot on one file `IdeCommands.*.cs`). |