Fix CLI-Reference discovery gap and unscoped alias segments (#137, #136) - #138
Conversation
MikroTik reshaped the CLI Reference from module pages into per-command leaf pages. Two defects surfaced, and they turn out to need each other. **Discovery (#137).** The sitemap serves a branching menu as a trailing-slash category URL with no .md of its own, while the menu's own Directory entry is published at `<dir>/<basename>.md` and listed only in llms.txt. Sitemap-only discovery dropped 256 of 1,070 pages — and the field-heavy quarter: fields came out at 5,944 instead of 10,938. Discovery is now the union of both inventories. The earlier "generated category stubs — every .md variant 404s" note was verified with the wrong candidate URLs; `<dir>/<basename>.md` returns 200 with a valid `**Type:** Directory` and full ArgTable. New blocking V-cliref-discovery gate asserts every category dir still contributes its leaf, so the next inventory change fails the build instead of quietly shrinking the corpus. **Alias scoping (#136).** KNOWN_ALIAS_SEGMENTS encoded "doc-internal module name" as a global property, but it is positional: `poe` and `qos` are real menu segments published elsewhere in the same source. Three entries linked to different commands with disjoint field sets (PoE-out vs SFP/link). A segment is now never dropped when the prefix ending at it is itself a published entry. Recovering the 256 Directory leaves is what publishes `interface/ethernet/switch/qos`, which lets the guard catch the third bad link — on the sitemap-only corpus it only reaches two. Rebuilt corpus (live, re-verified offline via --from-cache): pages 228 -> 1,070 fields 10,118 -> 10,938 entries 1,051 -> 1,077 flags 948 -> 976 links 931 (907 exact / 24 alias / 120 manual-only) -> 967 (967 exact / 0 alias / 110 manual-only) V-cliref-link-drift, V-cliref-db-integrity, full `bun test`, `make lint` and `make typecheck` all green. Closes #137 Closes #136 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (11)
📜 Recent review details⏰ Context from checks skipped due to timeout. (1)
🧰 Additional context used📓 Path-based instructions (11)*📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
**/*.md📄 CodeRabbit inference engine (CLAUDE.md)
Files:
MANUAL.md📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{ts,tsx,md}📄 CodeRabbit inference engine (AGENTS.md)
Files:
{README.md,MANUAL.md,src/setup.ts}📄 CodeRabbit inference engine (AGENTS.md)
Files:
VALIDATION.md📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{ts,tsx}📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Files:
src/**/*.{ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
DESIGN.md📄 CodeRabbit inference engine (CLAUDE.md)
Files:
CHANGELOG.md📄 CodeRabbit inference engine (CLAUDE.md)
Files:
briefings/B-*.md📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧠 Learnings (6)📚 Learning: 2026-07-12T20:33:29.883ZApplied to files:
📚 Learning: 2026-07-12T20:33:35.489ZApplied to files:
📚 Learning: 2026-07-12T20:33:29.883ZApplied to files:
📚 Learning: 2026-07-12T20:33:31.549ZApplied to files:
📚 Learning: 2026-07-12T20:33:42.621ZApplied to files:
📚 Learning: 2026-07-12T20:33:36.397ZApplied to files:
🔇 Additional comments (11)
📝 WalkthroughWalkthroughThe CLI-Reference extractor now discovers pages from sitemap and ChangesCLI-Reference discovery and validation
Crosswalk alias resolution
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Sitemap
participant LlmsTxt
participant Extractor
participant DiscoveryGate
Sitemap->>Extractor: provide sitemap URLs
LlmsTxt->>Extractor: provide Markdown inventory
Extractor->>DiscoveryGate: submit combined page inventory
DiscoveryGate-->>Extractor: accept complete directory coverage
sequenceDiagram
participant linkEntries
participant PublishedPaths
participant resolveEntry
linkEntries->>PublishedPaths: collect CLI-Reference source paths
linkEntries->>resolveEntry: resolve path with published paths
resolveEntry-->>linkEntries: exact, scoped alias, or manual-only link
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Updates the CLI-Reference ingestion and crosswalk logic to match MikroTik’s reshaped Docusaurus CLI Reference, ensuring the extracted corpus is complete and schema links are no longer silently mis-normalized.
Changes:
- Fix CLI-Reference discovery by taking the union of
sitemap.xmlandllms.txt, plus add a blocking validation gate to fail on trailing-slash category dirs that would otherwise drop Directory leaves (#137). - Scope alias-segment dropping in
link-clirefso an alias segment is never dropped when its prefix is itself a published entry, eliminating three incorrect schema links (#136). - Refresh documentation, validation rows, QA commentary, and the committed crosswalk baseline to reflect the new corpus shape and counts.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
VALIDATION.md |
Adds V-cliref-discovery and updates V-cliref-link-drift wording to match the new discovery + baseline model. |
src/extract-cliref.ts |
Implements union-based discovery (sitemap.xml ∪ llms.txt), excludes section index, and adds reconcileTrailingDirs() discovery-shape gate. |
src/extract-cliref.test.ts |
Adds tests for index exclusion, Directory-leaf preservation, and reconcileTrailingDirs() failure/pass behavior. |
src/link-cliref.ts |
Adds prefix-scoping to alias dropping by passing a publishedPaths set into resolveEntry(). |
src/link-cliref.test.ts |
Adds unit coverage for prefix-scoping behavior and default/unscoped behavior. |
cli-reference-links.tsv |
Updates the committed crosswalk baseline to the new corpus (967 exact / 0 alias / 110 manual-only / 1,077 entries). |
CHANGELOG.md |
Documents the user-visible fixes for discovery completeness (#137) and crosswalk correctness (#136). |
MANUAL.md |
Updates CLI-Reference overlay documentation (notably page count and discovery method) and references V-cliref-discovery. |
DESIGN.md |
Updates design rationale and adds a “source reshaped” section documenting the new discovery contract and consequences. |
briefings/B-0016-cli-reference-overlay-design.md |
Corrects the earlier category-page conclusion and records the reshaped-corpus findings. |
.github/workflows/qa.yml |
Updates overlay floor commentary to reflect the new observed corpus sizes. |
project-words.txt |
Adds new domain words (musicswitch, rbswitch) to keep spellchecking clean. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
mobileskyfi
left a comment
There was a problem hiding this comment.
gh pr review 138 --comment --body "Independent review (Hermes, 2026-08-12) — live census re-derived before reading this PR, so numbers below are re-measured not quoted.
Verified
- Live sitemap raw CLI locs 1,071 = 814 filtered + 257 trailing. Trailing includes section root -> 256 derived unique. Matches PR counts.
- llms.txt filtered 1,070 (index excluded) vs 1,071 raw. Union 814 + 256 = 1,070 = llms 1,070 exactly.
- Derived leaves are real pages: app/app (35 args), caps-man/interface/interface (79 args) each 200 with valid heading and Type Directory. Dropping 256 leaves silently lost the Directory menus.
- Field-count story: 5,944 on new source was not thinner source, it was the 256 missing Directory menus. After fix ~10,9xx correct.
- Alias scoping: 3 wrong links poE/qos -> disjoint field sets, prefix-scoping (never drop when prefix is published entry) derives from publication alone. Without guard 3 alias, with guard 0. Overlap filtered∩derived 0 so guard only fires on real published menu.
- bun test 1,117 pass on this branch, cli-reference-links header 967/0/110 matches fresh live sim.
Nits non-blocking
- reconcileTrailingDirs message names llms.txt as missing set but checks union (sitemap u llms). If sitemap later lists leaves, message will mislead while guard stays correct.
- --from-cache now needs both _sitemap.txt and _llms.txt cached, CLI help still says single flag. Worth a sentence in --help / MANUAL.
- index exclusion scoped to section root only, system/index preserved correctly - no issue, just noting edge handled.
No correctness concerns. The two fixes need each other as PR notes - recovering 256 Directory leaves publishes qos menu which lets guard reach third bad link."
- reconcileTrailingDirs named llms.txt as the missing set, but checks the union (sitemap ∪ llms.txt) — misleading if the sitemap later lists the leaves while the guard stays correct. Message now names the union. - Document that --from-cache needs both _sitemap.txt and _llms.txt: since #137 llms.txt is a discovery input, not just the sidebar labels. Noted in the module usage block and MANUAL.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Both actionable nits from the independent review are addressed in 612592a: Nit 1 — Nit 2 — Nit 3 — index exclusion scoped to the section root. Agreed, no change; Thanks for re-deriving the census independently rather than quoting the PR — that's what makes the +820 field delta trustworthy. |
* fix(catalog): discover CLI Reference from both inventories (#285) MikroTik reshaped the CLI Reference from module pages into per-command leaf pages whose slug is the CLI path. Fixed upstream in tikoci/rosetta#138; this is the centrs half. Discovery was the sitemap alone, which serves a branching menu as a trailing-slash category URL with no .md of its own. That menu's own entry IS published, at <dir>/<basename>.md, and listed only in llms.txt. Grounded live before touching code: sitemap 814 U derived <dir>/<basename> 256 = 1,070 = llms.txt (1,071 - index) Discovery is now the union, with a BLOCKING gate that every sitemap category dir contributes its leaf — the same assertion rosetta ships as V-cliref-discovery, so the next reshape fails loudly instead of quietly shrinking the table. A page only one inventory lists is reported rather than refused: the union already carries it, and --check fails on the new row anyway. Corpus now reconciles with rosetta exactly at 1,070 pages / 1,077 entries. The alias allowlist is empty, and that is the correct state. All 20 source spellings are gone from the publication and all 20 targets are published directly. R0/R1/R2 stay asserted so the next entry is refused rather than absorbed; the R1 test moved to a synthetic allowlist since no live entry exists. Two paths publish twice as containers under different hardware gates (/system/health as !i386 and health, /interface/ethernet/switch as musicswitch and rbswitch). Both halves say the path is navigation, so the row records what they agree on, exactly as a disagreed gate is dropped rather than picked. Only a navigation-vs-command split still aborts. Anchored on a new frozen fixture of the real page; "one entry per page" is explicitly not an invariant. Catalog: 1,119 -> 1,124 paths, 439 -> 450 commands, and the ancestry-aware unexplained residue 7 -> 1 (/interface/xfrm). Corpus differential over the 948-script corpus, old table vs new, harness verified by reproducing the #249 figures exactly on the old table: stmts 18,648 -> 18,648 argCandidates 14,329 -> 14,336 argReadable 7,385 -> 7,392 abstentions 6,944 -> 6,944 (48.4612% -> 48.4375%) context-lost 69 -> 83 Six scripts move and every statement in them is a correction. Seven newly resolve and read; five read the same with the right verb (/ip hotspot user reset-counters took `hotspot` as the verb, now takes `reset-counters`, which also reclassifies it as a write). No document changes containsWrite verdict. context-lost rising is the resolver withdrawing a certainty claim it should never have had: an unreadable statement might have been an absolute navigation and so restored context; a known command never navigated. Live --check is 1m34s cold, inside the QA job's 10-minute budget. Closes #285 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * review: resolve inventory-drift and test-anchor findings (#286) Three review findings, all fixed. Copilot — `discoverSlugs` reported the sitemap-only direction but never the inverse, while the docstring claimed both. The two directions are NOT symmetric, and that asymmetry is the shape: every sitemap page is also in llms.txt, but llms.txt legitimately carries 256 pages the sitemap lacks — those ARE the category leaves, so reporting them would bury the signal. The residue is what matters, and is now reported: an llms.txt page that is neither in the sitemap nor a category leaf has appeared from nowhere. CodeRabbit — `cliRefPath` used `new URL(link)`, which throws on a root-relative or document-relative link and so returned null, indistinguishable from "not a CLI page". Both inventories publish absolute URLs today (verified live), so this was latent rather than live, but a silent inventory shrink is exactly the #285 defect class. Links now resolve against the document they were read from. CodeRabbit — split the combined bare-word-head test. The abstention anchor (`/interface reset`) and the catalog-resolution anchor (`/interface reset-counters`) are separate mechanisms and now separate tests, so a catalog change is legible as one. Both new guards mutation-tested: reverting either fix turns its test red. `explain:catalog:check` still matches live — the catalog itself is unmoved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
MikroTik reshaped the CLI Reference from module pages into per-command leaf pages whose slug is the CLI path. Two defects surfaced. They turn out to need each other.
Discovery (#137)
The sitemap serves a branching menu as a trailing-slash category URL with no
.mdof its own. The menu's own Directory entry is published — at<dir>/<basename(dir)>.md(app/→app/app.md) — and listed only inllms.txt.Sitemap-only discovery therefore dropped 256 of 1,070 pages, and the field-heavy quarter of them:
cliref_fieldscame out at 5,944 instead of 10,938. Those menus, theirpackage/conditions/syscapgates, and their argument tables were absent from the DB, from thecli-reference/*export datasets, and from anything reading the overlay.Discovery is now the union of both inventories. Reconciles exactly:
The old
-- generated category pages ... every variant 404s (verified 2026-07-20)note was verified with the wrong candidate URLs —*.md,/index.mdand/.mdall 404, but<dir>/<basename>.mdreturns 200 with a valid**Type:** Directoryand full ArgTable. A 404 on a probe is evidence about the probe, not about the page.New blocking
V-cliref-discovery: every sitemap category dir must contribute its<dir>/<basename>leaf, or the build fails. That is the gate that would have caught this originally, and it fails loud in both directions rather than absorbing an inventory change.Alias scoping (#136)
KNOWN_ALIAS_SEGMENTSencoded "this word is a doc-internal module name" as a global property. It is positional:poeandqosare real menu segments published elsewhere in the same source. Three entries linked to different commands with disjoint field sets (PoE-out vs SFP/link; ~140 QoS per-queue fields vs 15 switch-port ones). Silent, because the alias branch only fires when the exact path is missing fromschema_nodes— precisely the hardware-gated commands nobody can check from a CHR.A segment is now never dropped when the prefix ending at it is itself a published entry. Isolated on the corrected corpus:
The two fixes need each other. Recovering the 256 Directory leaves is what publishes
interface/ethernet/switch/qos, which is what lets the guard see the third bad link. On the sitemap-only corpus the guard reaches only two of the three.Before / after
Live rebuild, re-verified offline via
--from-cache:v0.11.2-alpha.109)cliref_pagescliref_entriescliref_fieldscliref_flagscliref_entry_schema_linkscliref_field_inspect_links(view){1:95, 2:29, 3:33, …, 62:2}{1:1,063, 2:7}Export datasets move with it (
pages.tsv228→1,070,fields.tsv10,118→10,938,source/*.md228→1,070 files).Notes on the numbers
syscapgates (interface/ethernet/switch/portasmusicswitchwith 175 fields andrbswitchwith 139;system/healthasSettings DirectoryandDirectory). Occurrence identity stays the right model — "one entry per page" would be the wrong invariant to add.source_parent_idis now uniformlyNULL— it is intra-page heading ancestry and a one-heading page has none. Docs-only: no consumer branches on it.fixtures/cli-reference/sample.mddeliberately keeps the historical multi-entry shape, since it is what proves nesting still parses and no live page exercises it.interface/ethernetwent 35 → 160 fields on an unchanged path. Verified against live source (163<ArgTableRow>) — genuine upstream expansion, not an extraction artifact.Verification
bun test— 1,117 pass / 0 fail (new coverage for the discovery gate, theindexexclusion, and prefix-scoping in both directions)make lint,make typecheck— cleanV-cliref-link-drift,V-cliref-db-integrity— green on the rebuilt DBextract-cliref --from-cache --check-counts— reproduces the corpus offline, parsed==source markersCloses #137
Closes #136
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
llms.txtsources.Documentation