Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions GLOSSARY.txt
Original file line number Diff line number Diff line change
Expand Up @@ -684,4 +684,12 @@ unioned # of the two sources: merged with per-entry provenance rather than flatt
unioning # the act of the above
greppable # of a generated table: one entry per line, so `grep` finds a path
apos # the `'` XML entity, decoded by the CLI-Reference parser

# #285 CLI-Reference reshape vocabulary: the second published inventory, and the
# gate values on the paths that publish twice.
llms # `llms.txt` — MikroTik's published page inventory; the only one listing the `<dir>/<basename>` leaf a branching menu's own entry lives on, so discovery is the union of it and the sitemap
musicswitch # syscap gate: the Marvell-era switch-chip menu shape — one half of the `/interface/ethernet/switch` pair published under two gates
rbswitch # syscap gate: the RouterBOARD switch-chip menu shape — the other half of that pair
prestera # Marvell Prestera switch chip — named in the `crs_prestera` syscap gate on `/interface/ethernet/switch/qos`
xfrm # `/interface/xfrm` — the IPsec transform interface, and the one published path with no gate anywhere in its ancestry to explain its absence from a CHR tree
btrfs # the Linux B-tree filesystem, a `/disk/btrfs/...` menu on RouterOS 7.20+
65 changes: 54 additions & 11 deletions commands/explain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,20 +173,31 @@ today's path/verb/args split and script-vs-structured gate:
The *command* half is what #228 addressed, by adding a second first-order
source rather than a schema. MikroTik's CLI Reference is generated from the
definition structs, and measured against the same four pinned trees it has
**zero kind contradictions** across 906 exactly-matching paths, three RouterOS
versions and two architectures; 105 of the 112 published paths absent from
every tree carry a `package`/`conditions`/`syscap` gate that predicts the
absence. `src/explain/catalog.ts` unions the two with per-entry provenance,
which is what keeps `menus.ts`'s device-confirmed floor intact rather than
diluting it. The publication is not device truth: it uses the
definition-module spelling, so `caps-man/acl/access-list` is published and
unreachable on any device, and the hand-audited alias allowlist that recovers
the CLI spelling is guarded by two generation-time assertions. So
**zero navigation-vs-command contradictions** across 968 exactly-matching
paths, three RouterOS versions and two architectures; all but one of the 102
published paths absent from every tree carry a `package`/`conditions`/`syscap`
gate — their own or an ancestor's — that predicts the absence.
`src/explain/catalog.ts` unions the two with per-entry provenance, which is
what keeps `menus.ts`'s device-confirmed floor intact rather than diluting it.
The publication is still not device truth, but as of #285 it is at least
spelled like the CLI: MikroTik reshaped it from module pages into per-command
leaf pages whose slug *is* the CLI path, so the definition-module spellings
(`caps-man/acl/access-list`) are gone and the alias allowlist that recovered
them is empty — kept, and kept asserted, to refuse the next one loudly. So
`/system/reboot` now resolves as a `command` at `/system`, and the floor is
again unmoved — the residual is a path in *neither* table, such as
`/disk/format-drive`, which 7.23.2 spells `/disk format` and MikroTik does not
publish at all.

Discovery is the union of MikroTik's two published inventories, not the
sitemap alone. A *branching* menu is served as a trailing-slash category URL
with no `.md` of its own, while that menu's own entry is published at
`<dir>/<basename>.md` and listed only in `llms.txt` — so sitemap-only
discovery dropped 256 of 1,070 pages, silently and field-heavily. Generation
asserts that every category dir still contributes its leaf, so the next
inventory reshape fails loudly instead of shrinking the table (#285,
tikoci/rosetta#137).

There are real unknowns in how far offline parsing can go (expression
grammar, scope fidelity vs `:parse`, `[]`-nesting corner cases). Grounding
those unknowns was **phase 0** (#185); its findings are folded in throughout
Expand Down Expand Up @@ -899,13 +910,14 @@ The 948-script corpus contains no such continuation-comment argument case. The s
the corpus re-measurement below shows no readable/abstention movement — no
`do=`/`else=`/`command=`/`script=` brace sits inside an array in the 948
scripts, so the fix closes a device-grounded false `pass` with zero corpus
blast radius. The readable set stays exactly 7,385 statements. Recognizing a bracket-leading hash
blast radius. The readable set stayed exactly 7,385 statements. Recognizing a bracket-leading hash
as a comment conservatively folds two previously separate abstentions inside
one foreign kernel-panic transcript (`[#1]` / `[#2]`) into its already-unknown
outer statement, leaving 14,329 argument-bearing candidates and 6,944
abstentions (48.4612%). That two-statement movement is a blast-radius
measurement, not the grounding evidence; the two CHR versions above are the
oracle.
oracle. (Those are the #249-era figures; the #285 catalog correction has since
moved the readable set to 7,392 — see the re-measurement below.)

The same corpus run finds five new `invalid-hash` diagnostics, all in pasted
non-RouterOS material: one NGINX server block, one JavaScript highlighter, one
Expand All @@ -928,6 +940,37 @@ Corpus re-measurement for #249 — `bun -e 'explainCommand'` over the 948-script
expected outcome; the grounding remains the 15-input CHR probe below
(CHR 7.23.3 `highlight` at the `#` byte, 0/15 mismatches), not a corpus delta.

The #285 catalog correction moved those figures, and only upward. Same harness,
old table vs new:

| | #249 | #285 |
| --- | ---: | ---: |
| `stmts` | 18,648 | 18,648 |
| `argCandidates` | 14,329 | **14,336** |
| `argReadable` | 7,385 | **7,392** |
| `abstentions` | 6,944 | 6,944 (**48.4375%**) |
| `ambiguous-statement` | 91 | **85** |
| `unresolved-statement` | 3,911 | **3,910** |
| `context-lost` | 69 | **83** |

Six scripts move, and every statement in them is a correction. Seven statements
that read as `ambiguous`/`unknown` now resolve and their arguments read —
`/interface/monitor-traffic`, `/system/package/apply-changes`,
`/system/package/update/{check-for-updates,download,install}` — which is the
whole of the `argCandidates`/`argReadable` gain, with `abstentions` flat. Five
more read the same but with the right verb: `/ip hotspot user reset-counters
[find …]` took `hotspot` as the verb and 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, not
losing ground. It is `info` severity and marks a statement that resolved
correctly while the document context was already unknown. All 14 are in one
script — a bare list of command paths, one per line, with no navigation
anywhere. Previously `/interface/monitor-traffic` was 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, so the context stays as unknown as it already was.

- **Severity is fixed here, because it drives `--fail-on`.** Three buckets, and
the split is not "structural vs not":
- `error` — `unclosed`, `unbalanced-close`, `unterminated-string`,
Expand Down
Loading
Loading