CLI-613 Merge CAG subcommand tree into docs site#448
Conversation
✅ Deploy Preview for sonarqube-cli canceled.
|
sonar context is a Commander passthrough, so the docs generator cannot discover CAG's clap-based subcommands on its own. Wire the docs build to download the pinned CAG binary, invoke the new `tool dump-cli-tree --pretty` command, and stitch the result into commands.json / llms.txt / the HTML tree under the sonar-context entry. New files: - build-scripts/docs/dump-cag-tree.ts — download, verify, and run dump - build-scripts/docs/merge-cag-tree.ts — exported mergeCagTree + ClidocCommand types - tests/fixtures/cag-cli-tree.json — captured CAG tree fixture - tests/unit/build-scripts/docs/merge-cag-tree.test.ts — 18 unit tests Note: docs/data/commands.json and docs/llms.txt are not updated here. They will be regenerated (bun run gen:docs) once the CAG version in SONAR_CONTEXT_AUGMENTATION_VERSION is bumped to a release that includes the dump-cli-tree command. Set CAG_BINARY_PATH=<path> to use a local build during development.
…ctly Address Gitar review: - Clean up downloaded .tar.gz/.asc in a `finally` block so failed verifications don't leave unverified archives behind and successful runs don't waste cache. - Guard `JSON.parse` of the binary's stdout with an actionable error that includes stdout/stderr snippets. - Treat absence of `value_name` as the boolean-flag signal (CAG strips it upstream). Render variadic options (`num_args: "<min>+"`) with a trailing ellipsis (e.g. `--categories <CATEGORIES>...`). - Refresh fixture from updated CAG dump (boolean flags no longer carry value_name) and add regression tests for boolean/variadic rendering.
Address Gitar suggestion: CAG emits `default: "false"` for boolean flags that initialize to false. Surfacing this as `defaultValue` in the generated docs would advertise a stringified "false" as a meaningful default. Only carry defaultValue forward when the option actually accepts a value.
| export function mergeCagTree(cagTree: CagCliTree, allCommands: ClidocCommand[]): void { | ||
| const contextEntry = allCommands.find((c) => c.id === 'sonar-context'); | ||
| if (!contextEntry) { | ||
| throw new Error('sonar-context entry not found in allCommands — cannot merge CAG tree'); | ||
| } | ||
|
|
||
| contextEntry.isGroup = true; | ||
| contextEntry.arguments = []; | ||
| contextEntry.children = cagTree.subcommands.map((c) => `sonar-context-${c.name}`); | ||
|
|
||
| for (const cmd of cagTree.subcommands) { | ||
| addCagCommand(cmd, 'sonar-context', 'sonar context', 1, allCommands); | ||
| } |
There was a problem hiding this comment.
💡 Quality: CAG subcommands appended at array end, detached in llms.txt
mergeCagTree pushes all CAG entries onto the end of allCommands after every Commander command has already been serialized. commands.json/commands.html reconstruct the tree from children references so ordering there is fine, but buildLlmsTxt iterates allCommands sequentially (line 158). As a result the CAG sonar context … subcommand entries are emitted at the very bottom of llms.txt, far from the sonar context group header and out of the natural hierarchy that the rest of the file follows. This makes the generated llms.txt harder to read for the new subtree. Consider inserting the CAG entries immediately after the sonar-context entry (e.g. splice into allCommands at indexOf(contextEntry)+1) so the flat llms.txt ordering matches the tree.
Was this helpful? React with 👍 / 👎
| function takesValue(opt: CagOption): boolean { | ||
| if (!opt.value_name) return false; | ||
| if (opt.num_args && /^0(?![+0-9])/.test(opt.num_args)) return false; | ||
| return true; | ||
| } |
There was a problem hiding this comment.
💡 Edge Case: Boolean detection misclassifies optional-value flags (num_args 0..=1)
takesValue returns false when num_args matches /^0(?![+0-9])/. This is intended to catch zero-arg (0..=0) boolean flags, but it also matches 0..=1 (a flag that optionally accepts a value). Such an option would be rendered as a boolean with no <VALUE> placeholder, hiding the fact it can take a value. The current fixture only contains 1+/absent num_args so this is forward-compat only, but if CAG ever emits an optional-value flag the docs would be wrong. Consider only short-circuiting on an exact 0..=0/0 (max-args == 0) rather than any leading 0.
Was this helpful? React with 👍 / 👎
| description: cmd.about ?? '', | ||
| isGroup: hasChildren, | ||
| isRoot: false, | ||
| requiresAuth: !CAG_NON_AUTH_FULL_NAMES.has(fullName), |
There was a problem hiding this comment.
💡 Quality: Synthetic CAG group entries marked requiresAuth: true
Every CAG entry gets requiresAuth = !CAG_NON_AUTH_FULL_NAMES.has(fullName). Intermediate group/namespace entries (e.g. sonar context tool, sonar context navigation) are not in the non-auth set, so they are flagged requiresAuth: true. These groups are not executable commands, yet buildLlmsTxt appends the * auth marker to their headers (generate-docs.ts:161-162), producing e.g. ### sonar context tool * even though the tool start/stop/status/print-skill leaves under it are non-auth. Cosmetic, but the marker on a namespace is misleading. Consider leaving requiresAuth false (or omitting the marker) for isGroup entries.
Was this helpful? React with 👍 / 👎
Code Review 👍 Approved with suggestions 4 resolved / 7 findingsIntegrates CAG subcommands into the documentation site and fixes boolean flag rendering, but the boolean detection logic requires refinement for optional-value flags and authentication flagging for synthetic entries. 💡 Quality: CAG subcommands appended at array end, detached in llms.txt📄 build-scripts/docs/merge-cag-tree.ts:168-180 📄 build-scripts/docs/generate-docs.ts:140-141 📄 build-scripts/docs/generate-docs.ts:156-170
💡 Edge Case: Boolean detection misclassifies optional-value flags (num_args 0..=1)📄 build-scripts/docs/merge-cag-tree.ts:83-87
💡 Quality: Synthetic CAG group entries marked requiresAuth: true📄 build-scripts/docs/merge-cag-tree.ts:143 Every CAG entry gets ✅ 4 resolved✅ Quality: Boolean CAG flags rendered as value-taking options in docs
✅ Quality: dump-cag-tree leaves downloaded .tar.gz/.asc artifacts in cache
✅ Edge Case: JSON.parse of CAG stdout is unguarded
✅ Quality: Boolean CAG flags now carry a string "false" defaultValue
🤖 Prompt for agentsOptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change:
Was this helpful? React with 👍 / 👎 | Gitar |
|



Summary
build-scripts/docs/dump-cag-tree.ts: downloads the pinned CAG binary (PGP-verified, cached undernode_modules/.cache/), invokestool dump-cli-tree --pretty, and returns the parsed JSON treebuild-scripts/docs/merge-cag-tree.ts: exportedmergeCagTree(cagTree, allCommands)that stitches CAG subcommands under the existingsonar-contextentry, setsisGroup: true, clears the passthrough[action] [args...], maps options toClidocOption, and assignsrequiresAuthflagsgenerate-docs.tsto callawait dumpCagTree()+mergeCagTree()after the Commander tree is serializedsonar context guidelines get,sonar context dependencies check,sonar context navigation search-signaturestests/unit/build-scripts/docs/merge-cag-tree.test.tsusing the capturedtests/fixtures/cag-cli-tree.jsonfixtureContext:
sonar contextis a Commander passthrough — it just forwards args to the CAG binary. The docs generator walks Commander only, socommands.jsoncurrently showssonar-contextwithisGroup: false, children: []. This PR bridges the gap via the newtool dump-cli-treecommand added to CAG in SonarSource/sonar-context-augmentation#286.gen:docswill fail untilSONAR_CONTEXT_AUGMENTATION_VERSIONis bumped to a version that includesdump-cli-treeandbun run fetch:signaturesis refreshed. UseCAG_BINARY_PATH=<path-to-dev-build> bun run gen:docsfor local development.After the CAG version is bumped,
bun run gen:docsshould be re-run to commit updateddocs/data/commands.jsonanddocs/llms.txt.Test plan
bun test tests/unit/build-scripts/docs/merge-cag-tree.test.ts— 18 tests passbun test tests/unit/— 1578 pass, 0 fail (no regressions)bun run --bun tsc --noEmit— no new type errors (pre-existingpicomatcherror only)bun run gen:docssucceeds without overridedocs/data/commands.jsonhassonar-contextwithisGroup: trueand all CAG subcommand entriesdocs/llms.txtcontains### sonar context guidelines get *,### sonar context navigation search-signatures *, etc.docs/commands.html#sonar-contextlocally — Subcommands panel renders the full tree