fix(catalog): discover CLI Reference from both inventories (#285) - #286
Conversation
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>
|
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:
📝 WalkthroughWalkthroughThe PR migrates CLI Reference discovery to combined sitemap and ChangesCLI Reference catalog migration
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant CatalogGenerator
participant MikroTikSitemap
participant MikroTikLlmsTxt
participant discoverSlugs
participant CatalogFolder
participant GeneratedCatalog
CatalogGenerator->>MikroTikSitemap: fetch sitemap
CatalogGenerator->>MikroTikLlmsTxt: fetch llms.txt
MikroTikSitemap-->>discoverSlugs: sitemap XML
MikroTikLlmsTxt-->>discoverSlugs: inventory text
discoverSlugs-->>CatalogGenerator: unioned page slugs
CatalogGenerator->>CatalogFolder: parse and reconcile pages
CatalogFolder-->>GeneratedCatalog: catalog rows and gate metadata
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 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 explain CLI-Reference catalog generation to handle MikroTik’s reshaped CLI-Reference publication by discovering pages from the union of sitemap.xml and llms.txt, removing now-stale alias rewrites, and refreshing the generated catalog/table and its tests/fixtures accordingly.
Changes:
- Switch CLI-Reference discovery to
discoverSlugs(sitemap ∪ llms.txt)with a hard abort if any sitemap category directory would silently drop its<dir>/<basename>leaf. - Remove/lock down the alias allowlist as empty (with updated assertions and tests) and update catalog semantics around duplicated published paths and gate folding.
- Refresh unit tests, frozen fixtures, glossary, and
commands/explaindocumentation to match the new inventory shape and updated counts.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
scripts/explain-catalog-data.ts |
Adds union inventory discovery (sitemap.xml + llms.txt), category-leaf recovery, and updated published-entry folding rules. |
scripts/gen-explain-catalog.ts |
Fetches both inventories and uses the new union-based discovery during catalog generation/checking. |
src/explain/catalog.ts |
Updates the generated catalog table and its header documentation to reflect the new source inventory and semantics. |
test/unit/explain-catalog.test.ts |
Adds coverage for new discovery behavior and duplicated published-path handling. |
test/unit/explain-write.test.ts |
Updates write-detection anchors that changed due to the corrected catalog inventory. |
test/fixtures/explain/cliref/system__health__health.md |
Adds a new frozen fixture representing the new per-leaf page shape and duplicate path publication case. |
test/fixtures/explain/cliref/README.md |
Documents fixture purpose and the CLI-Reference reshape, including why older fixtures are intentionally retained. |
commands/explain/README.md |
Updates the explain command documentation to match the corrected inventory, discovery approach, and new measurements. |
GLOSSARY.txt |
Adds CLI-Reference reshape vocabulary (llms, musicswitch, rbswitch, etc.). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/explain-catalog-data.ts`:
- Around line 224-233: Update llmsSlugs so relative llms.txt links are not
silently discarded by cliRefPath: resolve supported root-relative and
path-relative targets against the correct llms.txt/CLI-reference base before
deriving pageSlug, or explicitly reject non-absolute targets with a visible
failure. Preserve slug collection and sorting for valid links.
In `@test/unit/explain-write.test.ts`:
- Around line 249-254: Split the combined test around containsWrite into two
tests: keep the existing bare-word “reset” assertions in “a bare-word head
abstains rather than clearing the document,” and move the
“/interface\nreset-counters” verdict assertion into a separate
catalog-resolution test. Preserve both expected verdicts and blockers.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 49616e39-767d-41a4-86f0-541111106d8b
📒 Files selected for processing (9)
GLOSSARY.txtcommands/explain/README.mdscripts/explain-catalog-data.tsscripts/gen-explain-catalog.tssrc/explain/catalog.tstest/fixtures/explain/cliref/README.mdtest/fixtures/explain/cliref/system__health__health.mdtest/unit/explain-catalog.test.tstest/unit/explain-write.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: CHR smoke (stable)
- GitHub Check: copilot-pull-request-reviewer
- GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (6)
{docs/**,.github/instructions/**,.github/**/*.yml,.github/**/*.yaml,**/*.{md,txt,dict}}
📄 CodeRabbit inference engine (AGENTS.md)
Run
bun run lint:ciwhen changing documentation, instructions, security configuration, spelling dictionaries, or workflow files.
Files:
GLOSSARY.txttest/fixtures/explain/cliref/README.mdtest/fixtures/explain/cliref/system__health__health.mdcommands/explain/README.md
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Transport or RouterOS-touching code is not done untilbun run test:integrationpasses.
Do not silently fall back to another protocol when the caller pinned--via.
Do not make generated output the hand-edited source of truth.
Do not disable validation to make a test pass; validation is part of the product.
Files:
scripts/gen-explain-catalog.tstest/unit/explain-write.test.tsscripts/explain-catalog-data.tstest/unit/explain-catalog.test.tssrc/explain/catalog.ts
test/fixtures/**/*
📄 CodeRabbit inference engine (test/AGENTS.md)
Keep fixtures under
test/fixtures/with clear source/provenance notes.
Files:
test/fixtures/explain/cliref/README.mdtest/fixtures/explain/cliref/system__health__health.md
commands/*/README.md
📄 CodeRabbit inference engine (commands/AGENTS.md)
commands/*/README.md: Eachcommands/<name>/README.mdis the executable specification's designed tier: document intent, flags, and behavior; include aDesigned, not implementedtable for spec-only flags; do not duplicate implemented-flag tables generated indocs/CLI.md; link todocs/CONSTITUTION.mdrather than restating constitution-wide rules; document only command-specific behavior; and keep theStatusline consistent withdocs/MATRIX.md.
Implemented flags must be generated fromCliCommandMetadataintodocs/CLI.mdviabun run docs:cli; command READMEs must not maintain duplicate tables of implemented flags.
Files:
commands/explain/README.md
commands/*/{README.md,examples.md}
📄 CodeRabbit inference engine (AGENTS.md)
Read the target command's
README.mdandexamples.mdas the executable specification before writing code or tests.
Files:
commands/explain/README.md
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/AGENTS.md)
src/**/*.{ts,tsx}: Use Bun-native TypeScript and Web APIs where possible
Errors must be actionable for humans and agents, with next-step guidance when a dependency, protocol, credential, or validation source is missing
Files:
src/explain/catalog.ts
🧠 Learnings (21)
📚 Learning: 2026-08-05T03:19:54.280Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 209
File: test/unit/explain-menus.test.ts:146-152
Timestamp: 2026-08-05T03:19:54.280Z
Learning: In `test/unit/explain-write.test.ts`, keep separate test anchors for `isDanglingBarePath` and menu-table rejection. Known menu paths such as `/ip/firewall/filter` and `/log` reach `isDanglingBarePath` at document end, while `/system/reboot` is rejected earlier by `isConfirmedNav` because `isMenuPath` returns false. Do not combine these inputs in one test when asserting coverage of either mechanism.
Applied to files:
test/unit/explain-write.test.tstest/fixtures/explain/cliref/README.mdcommands/explain/README.mdscripts/explain-catalog-data.tstest/unit/explain-catalog.test.tssrc/explain/catalog.ts
📚 Learning: 2026-08-06T14:17:50.227Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 224
File: commands/explain/examples.md:11-16
Timestamp: 2026-08-06T14:17:50.227Z
Learning: For the phase-1 offline explain API, offline behavior is tested through unit and fixture tests rather than CHR-backed integration tests. In `test/unit/explain-envelope.test.ts`, the CLI-spelling gate-versus-analysis behavior described by `commands/explain/examples.md` example `1b` and the resolved-menu behavior described by example `18b` have focused unit coverage. The CLI `explain` command surface is deferred and is not implemented as `src/cli/explain.ts` in this PR.
Applied to files:
test/unit/explain-write.test.tstest/fixtures/explain/cliref/README.mdcommands/explain/README.mdscripts/explain-catalog-data.tstest/unit/explain-catalog.test.ts
📚 Learning: 2026-08-01T23:46:54.392Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 197
File: src/explain/verbsplit.ts:383-387
Timestamp: 2026-08-01T23:46:54.392Z
Learning: In `src/explain/verbsplit.ts`, `VerbSplit` is the ratified Q6 boundary shape. Do not add document-scale context-certainty metadata to it independently; add that signal with the planned `ambiguous`/`unknown` verdict-vocabulary and phase-1 envelope work tracked in GitHub issue `#192`. Until then, `resolveVerbs` may correctly return root-based resolved paths for context-independent statements after context loss, but callers cannot observe that certainty was lost.
Applied to files:
test/unit/explain-write.test.tscommands/explain/README.md
📚 Learning: 2026-08-06T05:38:01.223Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 222
File: src/explain/defects.ts:1-70
Timestamp: 2026-08-06T05:38:01.223Z
Learning: In the TypeScript `src/explain` modules, references to phase-0 lab questions and issue numbers are an established documentation idiom when they explain the technical basis for a current contract. Keep these rationale references when they support implementation behavior. Remove dated decisions, delivery status, and future roadmap text from implementation and test comments.
Applied to files:
test/unit/explain-write.test.tstest/fixtures/explain/cliref/README.mdscripts/explain-catalog-data.tstest/unit/explain-catalog.test.ts
📚 Learning: 2026-08-05T20:06:21.299Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 217
File: src/explain/symbols.ts:0-0
Timestamp: 2026-08-05T20:06:21.299Z
Learning: In `src/explain/symbols.ts`, comparative corpus measurements that explain a semantic modeling trade-off are rule provenance and follow the established F1/F2 documentation convention. Treat run-specific bookkeeping, fuzz counts, scratch-script paths, method pointers, and per-version missed-tail details as status data that should not remain in source comments.
Applied to files:
test/unit/explain-write.test.tscommands/explain/README.mdscripts/explain-catalog-data.ts
📚 Learning: 2026-08-02T01:55:57.600Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 197
File: src/explain/pathresolve.ts:0-0
Timestamp: 2026-08-02T01:55:57.600Z
Learning: In `src/explain/pathresolve.ts`, `isUnreadablePath` identifies unreadable menu paths in both relative and absolute spelling. However, document-context poisoning applies only to unreadable `/`-led statements (`isUnreadableAbsolute`); relative unreadable paths do not poison document context by declared design.
Applied to files:
test/unit/explain-write.test.tsscripts/explain-catalog-data.tstest/unit/explain-catalog.test.ts
📚 Learning: 2026-08-11T17:46:27.539Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 273
File: test/fixtures/explain/corpus-partition.json:4-4
Timestamp: 2026-08-11T17:46:27.539Z
Learning: For durable fixtures in this repository, do not cite in-flight `.scratch/` files as provenance. In `test/fixtures/explain/corpus-partition.json`, the committed groups are the durable artifact, and the `frozen` no-regeneration statement replaces the former `.scratch/explain-lab-partition.ts` generator citation.
Applied to files:
test/fixtures/explain/cliref/README.md
📚 Learning: 2026-08-06T14:17:38.964Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 224
File: commands/explain/README.md:0-0
Timestamp: 2026-08-06T14:17:38.964Z
Learning: For the `explain` command documentation, `commands/explain/examples.md` specifies the finished target contract, not the current implementation phase. `commands/explain/README.md` contains the phase inventory and must map omitted phase fields to the issues and examples that will make them green. Future phase gaps must add fields without changing the finished example contract.
Applied to files:
test/fixtures/explain/cliref/README.mdcommands/explain/README.md
📚 Learning: 2026-08-06T23:42:39.898Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 227
File: src/explain/args.ts:151-158
Timestamp: 2026-08-06T23:42:39.898Z
Learning: For the RouterOS explain argument lexer corpus checks, a green frozen corpus measures coverage and risk but does not validate lexical rules absent from the corpus. The frozen corpus contains no lone-`\r` continuation case, so edge-case probes and targeted regression tests remain required for continuation behavior.
Applied to files:
test/fixtures/explain/cliref/README.mdcommands/explain/README.md
📚 Learning: 2026-07-23T00:15:08.643Z
Learnt from: CR
Repo: tikoci/centrs PR: 0
File: commands/AGENTS.md:0-0
Timestamp: 2026-07-23T00:15:08.643Z
Learning: Applies to commands/*/README.md : Each `commands/<name>/README.md` is the executable specification's designed tier: document intent, flags, and behavior; include a `Designed, not implemented` table for spec-only flags; do not duplicate implemented-flag tables generated in `docs/CLI.md`; link to `docs/CONSTITUTION.md` rather than restating constitution-wide rules; document only command-specific behavior; and keep the `Status` line consistent with `docs/MATRIX.md`.
Applied to files:
test/fixtures/explain/cliref/system__health__health.md
📚 Learning: 2026-06-08T22:26:06.293Z
Learnt from: CR
Repo: tikoci/centrs PR: 0
File: src/protocols/AGENTS.md:0-0
Timestamp: 2026-06-08T22:26:06.293Z
Learning: Applies to src/protocols/**/*router*{protocol,implementation,api,cli}*.{js,ts,md} : Ground protocol facts before implementation: RouterOS service/API/CLI path, auth model, default port, local tooling, validation source, security warnings, failure modes, and CHR test shape
Applied to files:
commands/explain/README.mdscripts/explain-catalog-data.tstest/unit/explain-catalog.test.tssrc/explain/catalog.ts
📚 Learning: 2026-08-06T22:07:13.134Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 226
File: commands/explain/README.md:0-0
Timestamp: 2026-08-06T22:07:13.134Z
Learning: For `centrs explain` documentation, an instructed remedy must be executable in the current phase. The live `centrs explain <router> --file -` form is parsed but returns `usage/not-implemented` until phase 2, so documentation must present the offline `--file -` form as the actionable stdin remedy.
Applied to files:
commands/explain/README.md
📚 Learning: 2026-06-08T22:25:53.303Z
Learnt from: CR
Repo: tikoci/centrs PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-06-08T22:25:53.303Z
Learning: Preserve RouterOS syntax and semantics. Do not add high-level RouterOS configuration helpers; that boundary is fixed in `docs/CONSTITUTION.md`
Applied to files:
commands/explain/README.md
📚 Learning: 2026-08-10T23:41:13.189Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 256
File: src/explain/args.ts:936-945
Timestamp: 2026-08-10T23:41:13.189Z
Learning: In `src/explain/args.ts`, `pushArrayMembers` must withdraw the enclosing array shape with `DEPTH_BOUND_REACHED` when `depth >= MAX_MEMBER_DEPTH`; returning `null` incorrectly reports the unverified literal as a valid array. CHR 7.23.3 accepts valid array nesting to at least depth 64, while invalid `(1,)` members remain syntax errors at all tested depths. The 948-script corpus has a maximum observed array-member depth of 6, so the depth-8 analysis bound does not drop observed valid corpus literals.
Applied to files:
commands/explain/README.md
📚 Learning: 2026-08-06T05:38:13.259Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 222
File: test/fixtures/explain/defects.json:3-73
Timestamp: 2026-08-06T05:38:13.259Z
Learning: In `src/explain/pathresolve.ts`, `Loc.base = -1` widening applies to defects raised during nested walker traversal, such as `over-depth`, when their local offsets cannot be mapped safely from UTF-16 string indexes to analyzed UTF-8 byte offsets. Defects emitted by the top-level segmenter are already in analyzed-document byte space and therefore retain precise offsets even when their enclosing statement contains non-ASCII text. The behavior is covered by `test/fixtures/explain/defects.json` and `test/unit/explain-defects.test.ts`.
Applied to files:
commands/explain/README.mdtest/unit/explain-catalog.test.ts
📚 Learning: 2026-06-08T22:26:06.293Z
Learnt from: CR
Repo: tikoci/centrs PR: 0
File: src/protocols/AGENTS.md:0-0
Timestamp: 2026-06-08T22:26:06.293Z
Learning: Applies to src/protocols/commands/**/*.{js,ts} : Surface missing local tools with platform-aware install or remediation advice
Applied to files:
scripts/explain-catalog-data.ts
📚 Learning: 2026-08-06T23:42:39.897Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 227
File: src/explain/args.ts:151-158
Timestamp: 2026-08-06T23:42:39.897Z
Learning: In the RouterOS explain lexer, `src/explain/args.ts` and `src/explain/verbsplit.ts` must use the shared `continuationLength(text, at)` helper for backslash-newline handling. Only `\n` and `\r\n` are continuations. A lone `\r` after `\` must not be skipped; `args.ts` must refuse it as an invalid escape to preserve source-accurate token names and spans.
Applied to files:
scripts/explain-catalog-data.ts
📚 Learning: 2026-06-16T10:51:07.659Z
Learnt from: CR
Repo: tikoci/centrs PR: 0
File: test/AGENTS.md:0-0
Timestamp: 2026-06-16T10:51:07.659Z
Learning: Applies to test/integration/**/*.test.{ts,js} : Put long-running, RouterOS-backed, or platform-specific tests (including process-level tests that spawn the real `src/cli.ts` through `cli-process.ts` and network-free CLI smoke tests in `cli-smoke.test.ts`) under `test/integration/` and wire them through QA or lab workflows.
Applied to files:
test/unit/explain-catalog.test.ts
📚 Learning: 2026-07-23T00:15:08.643Z
Learnt from: CR
Repo: tikoci/centrs PR: 0
File: commands/AGENTS.md:0-0
Timestamp: 2026-07-23T00:15:08.643Z
Learning: Use centered command verbs (`retrieve`, `execute`, `api`, `devices`, `discover`, `check`, `explain`, `terminal`, and `settings`) rather than one tool per RouterOS command; fold open-ended follow into `api --stream` rather than creating a separate `stream` verb.
Applied to files:
src/explain/catalog.ts
📚 Learning: 2026-08-07T16:47:13.907Z
Learnt from: CR
Repo: tikoci/centrs PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-07T16:47:13.907Z
Learning: Prefer `rosetta` MCP tools for RouterOS facts before using web search.
Applied to files:
src/explain/catalog.ts
📚 Learning: 2026-08-06T05:37:57.693Z
Learnt from: mobileskyfi
Repo: tikoci/centrs PR: 222
File: src/explain/defects.ts:1-70
Timestamp: 2026-08-06T05:37:57.693Z
Learning: In TypeScript modules under src/explain, retain references to phase-0 lab questions and issue numbers when they document the technical rationale for current implementation behavior or contracts. Remove comments containing dated decisions, delivery status, or future roadmap information when it does not explain current behavior, including in tests.
Applied to files:
src/explain/catalog.ts
🔇 Additional comments (12)
scripts/explain-catalog-data.ts (2)
26-52: LGTM!Also applies to: 94-138, 528-534, 660-674, 815-817, 831-835, 848-850, 1000-1004
195-222: LGTM!Also applies to: 235-289
scripts/gen-explain-catalog.ts (1)
20-32: LGTM!Also applies to: 114-121
test/unit/explain-catalog.test.ts (1)
32-40: LGTM!Also applies to: 151-159, 188-206, 285-296, 315-332, 380-411, 526-602, 666-691, 769-776
commands/explain/README.md (1)
176-200: LGTM!Also applies to: 913-920, 943-973
test/fixtures/explain/cliref/README.md (1)
3-27: LGTM!src/explain/catalog.ts (3)
12-14: LGTM!Also applies to: 27-35, 48-50, 90-101, 1323-1327
93-101: LGTM!Also applies to: 130-130, 155-155, 167-183, 227-238, 282-348, 366-366, 378-419, 429-472, 534-534, 558-559, 603-628, 659-698, 746-749, 760-811, 845-858, 877-878, 954-954, 987-988, 999-1007, 1025-1047, 1076-1089, 1106-1120, 1130-1132, 1172-1172, 1208-1211
283-286: 🗄️ Data Integrity & IntegrationKeep the
i386conditions. The published CLI Reference listsConditions: i386for both/interface/ethernetand/interface/ethernet/monitor.> Likely an incorrect or invalid review comment.GLOSSARY.txt (1)
687-694: LGTM!test/fixtures/explain/cliref/system__health__health.md (1)
1-90: LGTM!test/unit/explain-write.test.ts (1)
408-415: LGTM!
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>
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 (tikoci/rosetta#137 + tikoci/rosetta#136); this is the centrs half. The catalog audit abort after #279 was correct, and was not an isolated deletion.
1. Discovery is the union of both inventories, not the sitemap
The sitemap serves a branching menu as a trailing-slash category URL with no
.mdof its own. That menu's ownDirectoryentry is published — at<dir>/<basename>.md(app/→app/app.md) — and listed only inllms.txt. Grounded live before touching code:discoverSlugsnow unions both, and a blocking gate asserts every sitemap category dir still contributes its leaf — the same assertion rosetta ships asV-cliref-discovery, so the next reshape fails loudly instead of quietly shrinking the table. A page only one inventory lists is reported, not refused: the union already carries it, so nothing is dropped, and--checkfails on the new row anyway.indexis excluded explicitly — it is the argument-type glossary prose and publishes no**Type:**entry, so the loud-fail parser would (correctly) reject it.Corpus now reconciles with rosetta exactly: 1,070 pages / 1,077 entries.
2. The alias allowlist is empty, and that is the correct state
Re-audited every entry against the corrected inventory: zero of the twenty sources survive; twenty of twenty targets are published outright. The
caps-mandefinition modules,easymesh,serial-interface,ddns,ifaces,queues— all gone from the publication, each now published under its real CLI path.The machinery stays and stays asserted, because an allowlist that expects zero hits is exactly what should refuse the next one:
poe/qosare real menu segments, producing 3 wrong schema links rosetta#136 was missing.The R1 test moved to a synthetic allowlist, since the rule must be provable without a live entry. The product-side anchors stay green for a different reason than before, which is why they stay:
/caps-man/acl/access-listis absent and/caps-man/access-listpresent whichever mechanism is responsible.The reshape also silently fixed nine doc-spelled paths that were never in the allowlist —
/interface/pwr-link/pwr-line/*is now/interface/pwr-line/*.3. A path published twice as two container kinds is not a contradiction
Seven paths are published twice on one page under different hardware gates. Two of those pairs split
DirectoryagainstSettings Directory:Both halves say the path is navigation; they differ on whether this hardware's menu holds a single record. The row records what the occurrences agree on, exactly as a disagreed gate is dropped rather than picked — and nothing downstream distinguishes the two (
isKnownMenuaccepts either). Only a navigation-vs-command split still aborts.Anchored end-to-end on a new frozen fixture of the real page. "One entry per page" is explicitly not an invariant.
Catalog movement
menu/command/settings/interface/xfrm)both)42 added, 37 removed, 3 kind refinements, 272 gate changes (the recovered menu leaves carry gates their children inherit).
Corpus differential — 948 scripts, old table vs new
Harness verified by reproducing the #249 figures exactly on the old table before trusting it on the new one.
stmtsargCandidatesargReadableabstentionsambiguous-statementunresolved-statementcontext-lostSix scripts move, and every statement in them is a correction. Seven that read as
ambiguous/unknownnow resolve and their arguments read (/interface/monitor-traffic,/system/package/apply-changes,/system/package/update/{check-for-updates,download,install}) — the whole of theargCandidates/argReadablegain, withabstentionsflat. Five more read the same but with the right verb:/ip hotspot user reset-counters [find …]tookhotspotas the verb and now takesreset-counters, which also reclassifies it as a write. No document changescontainsWriteverdict. CRUD-verb read rate is bit-identical.context-lostrising is the resolver withdrawing a certainty claim, not losing ground — it isinfoseverity and marks a statement that resolved correctly while the context was already unknown. All 14 are in one script, a bare list of command paths with no navigation anywhere. Previously/interface/monitor-trafficwas unreadable and so might have been an absolute navigation, which R4 has REPLACE the context; certainty was restored on that maybe. Knowing it is a command, the resolver knows it never navigated.Verification
bun run lint,bun test(2,635 pass / 0 fail),bun run build,bun run lint:ci— all greenbun run explain:catalog:checkagainst live — committed table matches its two sources--checkis 1m34s (was ~30s), inside the QA job's 10-minute budget — no workflow change neededRefs: tikoci/rosetta#137, tikoci/rosetta#136, tikoci/rosetta#138, #228, #237, #279.
Closes #285
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
llms.txtinventories.Bug Fixes
Tests