@tikoci/centrs 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/GLOSSARY.txt +213 -0
- package/LICENSE +21 -0
- package/README.md +36 -8
- package/commands/AGENTS.md +7 -1
- package/commands/api/README.md +19 -18
- package/commands/api/examples.md +15 -0
- package/commands/btest/README.md +21 -32
- package/commands/check/README.md +6 -1
- package/commands/discover/README.md +5 -11
- package/commands/execute/README.md +41 -29
- package/commands/execute/examples.md +41 -3
- package/commands/explain/README.md +1716 -0
- package/commands/explain/examples.md +606 -0
- package/commands/retrieve/README.md +25 -27
- package/commands/retrieve/examples.md +16 -0
- package/commands/transfer/README.md +28 -20
- package/commands/transfer/examples.md +29 -0
- package/docs/CLI.md +353 -0
- package/docs/CONSTITUTION.md +66 -15
- package/docs/MATRIX.md +38 -1
- package/docs/errors/README.md +3 -0
- package/docs/errors/quickchr/machine-not-found.md +22 -0
- package/docs/errors/quickchr/machine-stopped.md +20 -0
- package/docs/errors/quickchr/package-unavailable.md +27 -0
- package/docs/errors/quickchr/unsupported-via.md +35 -0
- package/docs/errors/quickchr/unsupported.md +35 -0
- package/docs/errors/routeros/version-unsupported.md +26 -0
- package/docs/errors/transport/provider-trust.md +29 -0
- package/docs/errors/usage/stdin-ignored.md +28 -0
- package/docs/errors/validation/unknown-attribute.md +37 -4
- package/package.json +45 -10
- package/src/api-fanout.ts +29 -14
- package/src/api.ts +97 -54
- package/src/cli/api.ts +25 -6
- package/src/cli/btest.ts +18 -2
- package/src/cli/execute.ts +25 -6
- package/src/cli/explain.ts +503 -0
- package/src/cli/retrieve.ts +33 -1
- package/src/cli/selection.ts +71 -11
- package/src/cli/settings.ts +2 -2
- package/src/cli/transfer.ts +23 -6
- package/src/cli.ts +15 -2
- package/src/core/envelope.ts +5 -2
- package/src/core/error-catalog.ts +40 -0
- package/src/core/preflight.ts +306 -0
- package/src/core/routeros-string.ts +24 -0
- package/src/errors.ts +1 -0
- package/src/execute-fanout.ts +29 -14
- package/src/execute.ts +114 -63
- package/src/explain/arg-tokens.ts +114 -0
- package/src/explain/args.ts +1403 -0
- package/src/explain/blocks.ts +132 -0
- package/src/explain/brace-slots.ts +143 -0
- package/src/explain/brace-tokens.ts +38 -0
- package/src/explain/catalog.ts +1345 -0
- package/src/explain/coordinates.ts +329 -0
- package/src/explain/defects.ts +217 -0
- package/src/explain/is-known-menu.ts +17 -0
- package/src/explain/menus.ts +664 -0
- package/src/explain/operator-tokens.ts +310 -0
- package/src/explain/operators.ts +458 -0
- package/src/explain/path-tokens.ts +150 -0
- package/src/explain/pathresolve.ts +1324 -0
- package/src/explain/quoted-string.ts +241 -0
- package/src/explain/scope-brace.ts +308 -0
- package/src/explain/segment.ts +757 -0
- package/src/explain/string-tokens.ts +67 -0
- package/src/explain/symbol-values.ts +520 -0
- package/src/explain/symbols.ts +1597 -0
- package/src/explain/token-ranges.ts +72 -0
- package/src/explain/transport.ts +497 -0
- package/src/explain/value-tokens.ts +80 -0
- package/src/explain/values.ts +357 -0
- package/src/explain/verbs.ts +64 -0
- package/src/explain/verbsplit.ts +813 -0
- package/src/explain/write.ts +815 -0
- package/src/explain.ts +2152 -0
- package/src/index.ts +206 -4
- package/src/protocols/mac-telnet-console.ts +61 -17
- package/src/resolver/facts.ts +1 -1
- package/src/resolver/index.ts +23 -4
- package/src/resolver/quickchr-provider.ts +597 -0
- package/src/resolver/selection.ts +99 -12
- package/src/resolver/service-endpoint.ts +155 -0
- package/src/resolver/target.ts +1 -1
- package/src/retrieve-fanout.ts +26 -12
- package/src/retrieve.ts +81 -18
- package/src/transfer-fanout.ts +42 -25
- package/src/transfer.ts +87 -44
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,45 @@ documenting cross-cutting shifts that affect contributors and consumers.
|
|
|
8
8
|
|
|
9
9
|
## Unreleased
|
|
10
10
|
|
|
11
|
+
## 0.1.4 — 2026-08-31
|
|
12
|
+
|
|
13
|
+
Preview release. `@tikoci/centrs@0.1.4` on npm's `next` tag.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **Offline `explain` is now a real CLI and library surface.** It analyzes
|
|
18
|
+
RouterOS commands and scripts without a router, CDB, or network connection,
|
|
19
|
+
returning canonical structure, diagnostics, write-shape and transport
|
|
20
|
+
classification, optional `curl` rendering, symbols, value-shape hints, and a
|
|
21
|
+
gapless token partition. Try it with
|
|
22
|
+
`bunx @tikoci/centrs@next explain '/ip/address print' --json`.
|
|
23
|
+
- **Generated RouterOS structure evidence.** Pinned inspect trees and
|
|
24
|
+
MikroTik's published CLI Reference now help distinguish known menus from
|
|
25
|
+
commands while preserving the fail-closed rule: missing catalog entries never
|
|
26
|
+
become rejections, schema claims, or runtime-acceptance claims.
|
|
27
|
+
- **Named quickchr targets.** Router-facing commands can resolve an ephemeral
|
|
28
|
+
quickchr instance with `--quickchr <name>` through the shared target-provider
|
|
29
|
+
path.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **Offline analysis is substantially more precise and robust.** Grounded
|
|
34
|
+
handling now covers RouterOS comments, escapes, operators, arrays, value
|
|
35
|
+
shapes, path context, and flow-sensitive symbol-to-value references; bounded
|
|
36
|
+
traversal and shared statement indexes keep large inputs near-linear.
|
|
37
|
+
- **Release and QA coverage is broader.** Recency-aware RouterOS channel
|
|
38
|
+
selection, long-term-version expectations, generated-artifact drift checks,
|
|
39
|
+
corpus gates, and faster local Git gates make the published preview easier to
|
|
40
|
+
reproduce and audit.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **Validation now reads RouterOS `:parse` results instead of accepting the
|
|
45
|
+
transport round-trip alone**, and retrieve errors retain the rejected
|
|
46
|
+
parameter. Parser, catalog, cross-platform QA, and MAC-Telnet edge cases were
|
|
47
|
+
also hardened.
|
|
48
|
+
- **The npm package now carries the MIT license text.**
|
|
49
|
+
|
|
11
50
|
## 0.1.3 — 2026-07-06
|
|
12
51
|
|
|
13
52
|
Patch release. `@tikoci/centrs@0.1.3`.
|
package/GLOSSARY.txt
CHANGED
|
@@ -93,9 +93,12 @@ cwd
|
|
|
93
93
|
datagram
|
|
94
94
|
davidanson
|
|
95
95
|
DDNS
|
|
96
|
+
dialable # an endpoint a client can actually connect to (advertised AND reachable)
|
|
96
97
|
defconf
|
|
97
98
|
demux
|
|
98
99
|
demuxes
|
|
100
|
+
desync # a highlight stream whose token count != input length, so classes line up against the wrong characters
|
|
101
|
+
desynced
|
|
99
102
|
dogtail
|
|
100
103
|
donny
|
|
101
104
|
dotenv
|
|
@@ -125,6 +128,8 @@ keystream
|
|
|
125
128
|
KSA
|
|
126
129
|
KVM
|
|
127
130
|
LDTP
|
|
131
|
+
LFS # Git Large File Storage. The pinned corpus blob is NOT stored through it,
|
|
132
|
+
# which is why a plain raw.githubusercontent GET returns the real bytes.
|
|
128
133
|
librouteros # <https://github.com/haakonnessjoen/librouteros-api>
|
|
129
134
|
LLDP
|
|
130
135
|
lsp-routeros-ts
|
|
@@ -163,6 +168,7 @@ rosetta
|
|
|
163
168
|
routeros
|
|
164
169
|
routeros-skills
|
|
165
170
|
rsc # RouterOS script / export file extension (.rsc)
|
|
171
|
+
rstp # Rapid Spanning Tree Protocol; a RouterOS `protocol-mode=` value on /interface/bridge
|
|
166
172
|
SARIF # Static Analysis Results Interchange Format; CodeQL's code-scanning analysis download format
|
|
167
173
|
scp
|
|
168
174
|
scriptability
|
|
@@ -206,6 +212,7 @@ webproxy
|
|
|
206
212
|
WinAppDriver
|
|
207
213
|
winbox
|
|
208
214
|
Wireshark
|
|
215
|
+
workstream
|
|
209
216
|
workstreams
|
|
210
217
|
XCUI
|
|
211
218
|
XDG
|
|
@@ -269,6 +276,9 @@ choco
|
|
|
269
276
|
coderabbit
|
|
270
277
|
coderabbitai
|
|
271
278
|
|
|
279
|
+
# GitHub account Codex review threads are authored under (see pr-review-bots).
|
|
280
|
+
mobileskyfi
|
|
281
|
+
|
|
272
282
|
# centrs domain vocabulary
|
|
273
283
|
# %identity: the device /system/identity; a centrs CDB comment *lookup key*
|
|
274
284
|
# (`identity=`) used to resolve `<router>`. Human handle, deliberately may
|
|
@@ -370,6 +380,10 @@ CSI
|
|
|
370
380
|
SIGWINCH
|
|
371
381
|
# evl: RouterOS :parse renders a parsed command as "(evl ...)" on the console.
|
|
372
382
|
evl
|
|
383
|
+
# putmessage/globalname: RouterOS :parse IL statement heads — ":put x" echoes back
|
|
384
|
+
# as "(evl /putmessage=x)", ":global n v" as "(evl /globalname=$n;value=v)" (GH#230).
|
|
385
|
+
putmessage
|
|
386
|
+
globalname
|
|
373
387
|
# unconfigured: a freshly-flashed RouterOS device with no IP — the mac-telnet use case.
|
|
374
388
|
unconfigured
|
|
375
389
|
unwired
|
|
@@ -397,6 +411,7 @@ Weierstrass
|
|
|
397
411
|
# ndjson: newline-delimited JSON; the stream / btest output contract (one envelope per line).
|
|
398
412
|
ndjson
|
|
399
413
|
# allocate-udp-ports-from: /tool/bandwidth-server base of the UDP data-port range.
|
|
414
|
+
allocate-udp-ports-from
|
|
400
415
|
# srp5: the "5" suffix of EC-SRP5 (the MikroTik EC-SRP variant).
|
|
401
416
|
srp5
|
|
402
417
|
# SRV: the server-endpoint test variable in commands/btest/examples.md.
|
|
@@ -505,3 +520,201 @@ sfo
|
|
|
505
520
|
ele
|
|
506
521
|
GPX
|
|
507
522
|
Geolocation
|
|
523
|
+
unparseable
|
|
524
|
+
Unparseable
|
|
525
|
+
versionless
|
|
526
|
+
|
|
527
|
+
# explain canonicalizer (phase-0 lab #185, commands/explain) vocabulary.
|
|
528
|
+
# SUT: "system under test" — the phase-0 lab's throwaway parser, scored
|
|
529
|
+
# against a `:parse` IL / highlight oracle; the ratified behavior is what the
|
|
530
|
+
# production modules under src/explain promote. CJK: the Chinese/Japanese/
|
|
531
|
+
# Korean Unicode range, used as a non-ASCII coordinate/segmentation fixture.
|
|
532
|
+
# pathresolve / blocktree: the Q3-Q4 / Q2 lab probe names, carried into the
|
|
533
|
+
# src/explain module + fixture names. klass: `class` is reserved, so the
|
|
534
|
+
# resolution feature-class field is `klass`. tostr / tostrvalue: the RouterOS
|
|
535
|
+
# `:tostr` directive and its IL-lowered form `/tostrvalue`. eworm: a corpus
|
|
536
|
+
# script author (eworm/*.rsc) cited as grounding for scope-name findings.
|
|
537
|
+
# rextended: another corpus script author, cited for the Q14 nested-bracket
|
|
538
|
+
# ambient-context case (a user function establishes no menu). ppp: the RouterOS
|
|
539
|
+
# /ppp menu, in the Q14 corner proving a `$` inside a `~` FILTER argument does
|
|
540
|
+
# not make the menu unreadable. strfind: a corpus user function in that corner.
|
|
541
|
+
# verbsplit: the Q6 verb/menu-boundary lab probe name, carried into the
|
|
542
|
+
# src/explain module + fixture names. myvar: the RouterOS example variable in
|
|
543
|
+
# the Q6 `:global myvar` collision corner (a positional operand indistinguishable
|
|
544
|
+
# from a sub-menu offline).
|
|
545
|
+
# failclosed: the ratified Q16 navigation arm name (the two arms that priced it
|
|
546
|
+
# stayed in the lab). notadirective: the Q16 fixture's deliberately unseen root
|
|
547
|
+
# directive, pinning that an unknown directive abstains rather than reading as
|
|
548
|
+
# harmless control flow.
|
|
549
|
+
# RouterOS root cmds (scripting directives) enumerated from /console/inspect and
|
|
550
|
+
# frozen in src/explain/write.ts as the closed ROOT_CMDS vocabulary — jobname,
|
|
551
|
+
# rndnum, rndstr, tobool, tocrlf, toid, toip, tolf, tonsec, tonum, totime.
|
|
552
|
+
# lte: the RouterOS /interface lte menu, cited in the Q16 long-tail-verb corner.
|
|
553
|
+
# dyn: the `$dyn` variable in the Q14 cascade corners — a dynamic-headed
|
|
554
|
+
# statement, which is context-NEUTRAL and must not poison the menu context.
|
|
555
|
+
# symbols (Q13): cls — the resolved variable-class field on a symbol occurrence
|
|
556
|
+
# (`class` is reserved, same reason as klass). sigilled: written with the `$`
|
|
557
|
+
# sigil, the schema-free tell that separates a variable from a directive or a
|
|
558
|
+
# menu-path segment. ERRVAR: the `:onerror NAME` error-variable slot (S18).
|
|
559
|
+
# unmodeled / distinguisher: the closure-scope finding — the lab left the rule
|
|
560
|
+
# unmodeled because a depth counter has no scope identity, and the statement
|
|
561
|
+
# head is the only distinguisher between a function `do={}` and a control-flow
|
|
562
|
+
# one. Corner variable names quoted from the device probes and corpus scripts:
|
|
563
|
+
# vlanid, vlanbytes, ipprefix, octive (the `$octive-1` name-vs-operator case),
|
|
564
|
+
# lppp (the device documentation's own `variable-undefined` example).
|
|
565
|
+
# lookback: the backward scan that decides whether a `{` follows `do=`; it must
|
|
566
|
+
# accept exactly the escapes the forward walker does, or the two disagree about
|
|
567
|
+
# where the argument name ends and a function body stops being a closure.
|
|
568
|
+
# tangentsoft: the maintainer/site (tangentsoft.com/mikrotik) behind the third
|
|
569
|
+
# corpus collection — 35 genuine `/export show-sensitive terse` device captures
|
|
570
|
+
# imported for the #203 genre census, and the corpus's only wholly-terse
|
|
571
|
+
# export stratum.
|
|
572
|
+
SUT
|
|
573
|
+
CJK
|
|
574
|
+
parseil # lsp-routeros-ts corpus table of captured `:parse` IL, per script per RouterOS version
|
|
575
|
+
pathresolve
|
|
576
|
+
blocktree
|
|
577
|
+
klass
|
|
578
|
+
tostr
|
|
579
|
+
tostrvalue
|
|
580
|
+
eworm
|
|
581
|
+
rextended
|
|
582
|
+
tangentsoft
|
|
583
|
+
ppp
|
|
584
|
+
strfind
|
|
585
|
+
verbsplit
|
|
586
|
+
myvar
|
|
587
|
+
failclosed
|
|
588
|
+
notadirective
|
|
589
|
+
jobname
|
|
590
|
+
rndnum
|
|
591
|
+
rndstr
|
|
592
|
+
tobool
|
|
593
|
+
tocrlf
|
|
594
|
+
toid
|
|
595
|
+
toip
|
|
596
|
+
tolf
|
|
597
|
+
tonsec
|
|
598
|
+
tonum
|
|
599
|
+
totime
|
|
600
|
+
lte
|
|
601
|
+
dyn
|
|
602
|
+
cls
|
|
603
|
+
sigilled
|
|
604
|
+
ERRVAR
|
|
605
|
+
unmodeled
|
|
606
|
+
distinguisher
|
|
607
|
+
vlanid
|
|
608
|
+
vlanbytes
|
|
609
|
+
ipprefix
|
|
610
|
+
octive
|
|
611
|
+
lppp
|
|
612
|
+
lookback
|
|
613
|
+
|
|
614
|
+
# RouterOS menu vocabulary reached by the explain menu table (#207).
|
|
615
|
+
# The generated table itself (src/explain/menus.ts) is cspell-ignored; these are
|
|
616
|
+
# the terms that also appear in hand-written prose and tests.
|
|
617
|
+
# %cliref: docs-derived RouterOS command reference in rosetta
|
|
618
|
+
# (experiments/cliref.db). A second opinion on node types, NOT a source for
|
|
619
|
+
# the menu table: its paths interleave the docs slug with the CLI path.
|
|
620
|
+
cliref
|
|
621
|
+
hotspot
|
|
622
|
+
igmp
|
|
623
|
+
ipfix
|
|
624
|
+
keymat
|
|
625
|
+
pmp
|
|
626
|
+
pptp
|
|
627
|
+
sstp
|
|
628
|
+
wlan
|
|
629
|
+
zerotier
|
|
630
|
+
cuu # `/terminal cuu` (cursor up) — a RouterOS command that reads as a bare menu path, so the table refuses it (#210)
|
|
631
|
+
|
|
632
|
+
# Hardware-gated RouterOS surfaces named when explaining why a published path is
|
|
633
|
+
# absent from a CHR-derived inspect tree (#228). No CHR carries these.
|
|
634
|
+
FDB # forwarding database — `/interface/ethernet/switch/{unicast,multicast,reserved}-fdb`, switch-chip only
|
|
635
|
+
MSRP # Stream Reservation Protocol (TSN) — `/interface/bridge/msrp`, gated by `conditions: MSRP_ENABLE`
|
|
636
|
+
PTP # Precision Time Protocol — `/system/ptp`, gated by `syscap: ptp`
|
|
637
|
+
syscap # a CLI-Reference applicability gate naming the hardware/system capability a path requires (`poe`, `lcd`, `multiswitch`, `nochr`)
|
|
638
|
+
|
|
639
|
+
# explain ANALYSIS/ORACLE vocabulary — not RouterOS menu names. These name the
|
|
640
|
+
# lab's measurement machinery and the properties it measures, and belong apart
|
|
641
|
+
# from the menu block above even though both arrived with the explain work.
|
|
642
|
+
importability # whether a document RouterOS emitted can be re-imported (#203 oracle level L2)
|
|
643
|
+
menuctx # the IL (`:parse`) statement type for menu navigation, as against `cmd` — the native nav-vs-command oracle (#210)
|
|
644
|
+
|
|
645
|
+
# #202c-1 argument-lexer vocabulary: one analysis term, plus the RouterOS names
|
|
646
|
+
# that appear verbatim in the corpus lines `test/unit/explain-args.test.ts`
|
|
647
|
+
# fixtures. The corpus lines are real forum scripts and are quoted rather than
|
|
648
|
+
# paraphrased, so their spellings are data, not prose.
|
|
649
|
+
renderable # of a statement: covered by a tested REST mapping rule, so `--curl` may render it (#202c-2)
|
|
650
|
+
wifiwave # `/interface wifiwave2` — the pre-7.13 RouterOS wifi menu, renamed `wifi` (drift the corpus carries)
|
|
651
|
+
nomaster # from a corpus line where two arguments ran together (`disabled=nomaster-interface=wifi1`); pinned as the first-`=`-splits case
|
|
652
|
+
CAINFO # `AT#CAINFO?` — an LTE modem AT command in a corpus `/interface/lte/at-chat` line
|
|
653
|
+
vzwinternet # Verizon LTE APN name, from a corpus `/interface lte apn add` line
|
|
654
|
+
rtr # short device name in an explain test input
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
# #228 path-catalog vocabulary: the CLI-Reference definition-module segments the
|
|
658
|
+
# alias allowlist maps away, the published gate values, and the prose terms used
|
|
659
|
+
# to describe the union. The generated table itself is cspell-ignored.
|
|
660
|
+
chancfg # caps-man definition module for `/caps-man/channel` — a doc spelling, not a CLI path
|
|
661
|
+
dpathcfg # caps-man definition module for `/caps-man/datapath`
|
|
662
|
+
ifaceactual # caps-man definition module for `/caps-man/actual-interface-configuration`
|
|
663
|
+
ratescfg # caps-man definition module for `/caps-man/rates`
|
|
664
|
+
remoteap # caps-man definition module for `/caps-man/remote-cap`
|
|
665
|
+
seccfg # caps-man definition module for `/caps-man/security`
|
|
666
|
+
ifaces # CLI-Reference definition module for `/tool/graphing/interface`
|
|
667
|
+
datapath # `/caps-man/datapath` — the real CLI menu behind `dpathcfg`
|
|
668
|
+
easymesh # `/interface/wifi/easymesh` — the doc spelling of `/interface/wifi/wps-push-button`
|
|
669
|
+
wps # Wi-Fi Protected Setup — `/interface/wifi/wps-push-button`
|
|
670
|
+
qos # switch-chip quality of service — `/interface/ethernet/switch/qos`, a real menu segment R1 must never drop
|
|
671
|
+
qca # Qualcomm Atheros — the `wireless-qca` package gate
|
|
672
|
+
multiswitch # syscap gate: more than one switch chip
|
|
673
|
+
oldswitch # syscap gate: the pre-Prestera switch-chip menu shape
|
|
674
|
+
smips # RouterOS architecture (single-core MIPS), named in `conditions:` gates
|
|
675
|
+
mmips # RouterOS architecture (multi-core MIPS), named in `conditions:` gates
|
|
676
|
+
CRS # MikroTik Cloud Router Switch — carries the switch-chip menus no CHR has
|
|
677
|
+
CCR # MikroTik Cloud Core Router
|
|
678
|
+
superlinear # growth faster than linear, used for resolveDocument wall-clock on separator-free input (#248)
|
|
679
|
+
stmts # `explainCommand` corpus measurement: statement count (shorthand for `statements`)
|
|
680
|
+
argCandidates # `explainCommand` corpus measurement: arg-bearing candidates
|
|
681
|
+
argReadable # `explainCommand` corpus measurement: readable statements
|
|
682
|
+
ungated # of a published path: carrying no package/conditions/syscap that would explain its absence from a tree
|
|
683
|
+
unioned # of the two sources: merged with per-entry provenance rather than flattened
|
|
684
|
+
unioning # the act of the above
|
|
685
|
+
greppable # of a generated table: one entry per line, so `grep` finds a path
|
|
686
|
+
apos # the `'` XML entity, decoded by the CLI-Reference parser
|
|
687
|
+
|
|
688
|
+
# #285 CLI-Reference reshape vocabulary: the second published inventory, and the
|
|
689
|
+
# gate values on the paths that publish twice.
|
|
690
|
+
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
|
|
691
|
+
musicswitch # syscap gate: the Marvell-era switch-chip menu shape — one half of the `/interface/ethernet/switch` pair published under two gates
|
|
692
|
+
rbswitch # syscap gate: the RouterBOARD switch-chip menu shape — the other half of that pair
|
|
693
|
+
prestera # Marvell Prestera switch chip — named in the `crs_prestera` syscap gate on `/interface/ethernet/switch/qos`
|
|
694
|
+
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
|
|
695
|
+
btrfs # the Linux B-tree filesystem, a `/disk/btrfs/...` menu on RouterOS 7.20+
|
|
696
|
+
|
|
697
|
+
# #255 operator-axis vocabulary: the device-grounded operator surface.
|
|
698
|
+
arities # plural of arity — the operand counts an operator accepted, which is what separates `(> 1)` (deferred expression) from `(2 > 1)` (comparison)
|
|
699
|
+
typeofvalue # RouterOS IL renders `[:typeof $x]` as `/typeofvalue=$x` — the directive and its argument name run together with no separator
|
|
700
|
+
juxt # short for juxtaposition — the unnamed ` ( a b)` node RouterOS builds for space-separated paren contents; used in ids like `any-juxt`
|
|
701
|
+
punct # short for punctuation — the shape class for a candidate spelling made of symbol bytes, as opposed to a word; used in the `bogus-punct` control id
|
|
702
|
+
gapless # of a token partition: every byte in [0, input.bytes) belongs to exactly one token, sorted by start, no gaps (#289 B1)
|
|
703
|
+
SCIP # Source Code Intelligence Protocol — the symbol-identity axis for `data.tokens[]`'s later vocabulary (#264 B5)
|
|
704
|
+
unclassified # the provisional token class for a byte no analyzer claims; a first-class answer in the gapless partition (#289 B1)
|
|
705
|
+
|
|
706
|
+
# #290 B2 operator-fill test vocabulary
|
|
707
|
+
xand
|
|
708
|
+
andx
|
|
709
|
+
alnum
|
|
710
|
+
wpa # `security.authentication-types=wpa2-psk` — a wifi argument name whose interior dot the operator fill must not read as concatenation
|
|
711
|
+
psk # pre-shared key — the value half of the same grounded `wpa2-psk` example
|
|
712
|
+
|
|
713
|
+
# #293 B2 arg-fill vocabulary
|
|
714
|
+
retag # B5 may retag the `=` separator from the provisional `arg` class without moving byte coverage
|
|
715
|
+
|
|
716
|
+
# #239 S2 flow-sensitive symbol→value
|
|
717
|
+
occ # short for occurrence — local variable in symbol-values flow analysis
|
|
718
|
+
vid # short for valueId — result-local value occurrence identifier (v0, v1)
|
|
719
|
+
idx # short for index — loop/event index in flow merging
|
|
720
|
+
mis # prefix in mis-linking — hyphenated in comments for symbol-values guard
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TIKOCI GitHub Organization
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -4,12 +4,21 @@
|
|
|
4
4
|
CLI (with MCP, TUI, and HTTP proxy frontends planned) for talking to MikroTik
|
|
5
5
|
RouterOS devices through a regularized, validated interface.
|
|
6
6
|
|
|
7
|
-
Preview builds are published on npm. To
|
|
7
|
+
Preview builds are published on npm. To try the current offline analyzer without
|
|
8
|
+
installing centrs or connecting to a router:
|
|
8
9
|
|
|
9
10
|
```bash
|
|
10
|
-
bunx @tikoci/centrs --
|
|
11
|
+
bunx @tikoci/centrs@next explain '/ip/address print' --json
|
|
11
12
|
```
|
|
12
13
|
|
|
14
|
+
Use `bunx @tikoci/centrs@next --help` to inspect the full preview CLI. The
|
|
15
|
+
explicit `@next` matters: `0.1.x` preview releases do not move npm's `latest`
|
|
16
|
+
tag.
|
|
17
|
+
|
|
18
|
+
The full flag reference for every command is generated from the CLI metadata
|
|
19
|
+
into [`docs/CLI.md`](docs/CLI.md); per-command behavior lives in
|
|
20
|
+
`commands/<name>/README.md`.
|
|
21
|
+
|
|
13
22
|
It is a **friendly conduit**, not a high-level configuration abstraction. It
|
|
14
23
|
helps humans and agents reach RouterOS over the right protocol, with the right
|
|
15
24
|
credentials and ports, and validates RouterOS-shaped commands before running
|
|
@@ -17,9 +26,12 @@ them. It does **not** hide RouterOS behind helpers like `createVlanOnBridge()`
|
|
|
17
26
|
— you still speak RouterOS. Validation and structured diagnostics are the
|
|
18
27
|
product; without them this would just be a worse `curl`.
|
|
19
28
|
|
|
20
|
-
> **Status:** early npm preview
|
|
21
|
-
>
|
|
22
|
-
>
|
|
29
|
+
> **Status:** early npm preview under active development. It is not
|
|
30
|
+
> production-ready: expect bugs and breaking changes before 1.0, and exercise
|
|
31
|
+
> router-writing workflows on lab or disposable targets first. Offline
|
|
32
|
+
> `explain` does not contact a router, but its analysis is intentionally
|
|
33
|
+
> conservative and never proves that RouterOS will accept a command at runtime.
|
|
34
|
+
> Check current dist-tags with
|
|
23
35
|
> `npm view @tikoci/centrs dist-tags --json`. The library, device registry, and
|
|
24
36
|
> first MCP server phases are CHR-verified; the CLI is wired (`coded`);
|
|
25
37
|
> encrypted-CDB writes are still blocked, and the TUI/proxy frontends are planned.
|
|
@@ -35,8 +47,10 @@ product; without them this would just be a worse `curl`.
|
|
|
35
47
|
SSH / MAC-Telnet / RoMON / WinBox Terminal for interactive and L2 execute;
|
|
36
48
|
MNDP for discovery. centrs picks the protocol for you (and lets you pin one
|
|
37
49
|
with `via=` or `--via`).
|
|
38
|
-
- **Commands:** every command resolves a *target* — a router you
|
|
39
|
-
CLI — to a real address, credentials, and a protocol, then runs.
|
|
50
|
+
- **Commands:** every router-facing command resolves a *target* — a router you
|
|
51
|
+
name on the CLI — to a real address, credentials, and a protocol, then runs.
|
|
52
|
+
(Local commands — `devices`, `settings`, `discover`, and `explain`'s offline
|
|
53
|
+
mode — need no router.)
|
|
40
54
|
|
|
41
55
|
| Command | Purpose |
|
|
42
56
|
| ---------- | ------- |
|
|
@@ -45,6 +59,7 @@ product; without them this would just be a worse `curl`.
|
|
|
45
59
|
| `api` | Structured RouterOS API passthrough (gh-api style): one command per operation, structured in/out, can write, over REST or native API. Open-ended follow is `api … --stream` (native API; NDJSON). |
|
|
46
60
|
| `terminal` | Open an interactive console, primarily SSH or MAC-Telnet. |
|
|
47
61
|
| `check` | Probe reachability and management protocol availability. |
|
|
62
|
+
| `explain` | Analyze a RouterOS command before running it: canonical form, syntax diagnostics, and what is valid at a path. Offline analysis runs today; the live-device probes are designed. |
|
|
48
63
|
| `devices` | View and maintain the CDB-backed device registry (the only writer). |
|
|
49
64
|
| `discover` | Discover MNDP neighbors and optionally save them into the CDB. |
|
|
50
65
|
| `settings` | Manage centrs's own settings (`centrs.env`, `__default__`) and run first-time setup. |
|
|
@@ -184,7 +199,7 @@ roadmap.
|
|
|
184
199
|
|
|
185
200
|
Requirements:
|
|
186
201
|
|
|
187
|
-
- Bun 1.3.11 or newer (CI pinned to 1.3.
|
|
202
|
+
- Bun 1.3.11 or newer (CI pinned to 1.3.14; Bun 2.x not yet validated).
|
|
188
203
|
- Git.
|
|
189
204
|
- For integration tests: QEMU plus `@tikoci/quickchr` (handles CHR image
|
|
190
205
|
download and boot).
|
|
@@ -204,6 +219,19 @@ Generated API docs through TypeDoc:
|
|
|
204
219
|
bun run build:doc:api
|
|
205
220
|
```
|
|
206
221
|
|
|
222
|
+
The `explain` censuses measure a RouterOS script corpus that lives in
|
|
223
|
+
[`tikoci/lsp-routeros-ts`](https://github.com/tikoci/lsp-routeros-ts), not in
|
|
224
|
+
this repo. `scripts/corpus-pin.json` records which snapshot centrs measures
|
|
225
|
+
against — a commit plus the blob's sha256 — and `corpus:fetch` downloads and
|
|
226
|
+
verifies it. A sibling `lsp-routeros-ts` checkout is used when present, and the
|
|
227
|
+
censuses print the source and hash they used:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
bun run corpus:fetch # download the pinned snapshot, verify its sha256
|
|
231
|
+
bun run explain:corpus-census # genre census (#203)
|
|
232
|
+
bun run explain:value-census # value-surface census (#225)
|
|
233
|
+
```
|
|
234
|
+
|
|
207
235
|
## Done definition (short version)
|
|
208
236
|
|
|
209
237
|
A feature is done when every line in `commands/<name>/examples.md` is green on
|
package/commands/AGENTS.md
CHANGED
|
@@ -7,6 +7,11 @@ Each `commands/<name>/` holds the **executable spec** for one command:
|
|
|
7
7
|
the matching `test/integration/<name>.test.ts`; example N ↔ assertion N. This
|
|
8
8
|
is what `CHR-passed` is measured against.
|
|
9
9
|
|
|
10
|
+
**Implemented** flags are generated from `CliCommandMetadata` into
|
|
11
|
+
`docs/CLI.md` (`bun run docs:cli`; drift-gated in CI) — a command README keeps
|
|
12
|
+
behavior prose plus a "Designed, not implemented" table for spec-only flags,
|
|
13
|
+
never a duplicate table of implemented flags.
|
|
14
|
+
|
|
10
15
|
Do not restate the constitution here or in a command README — link to
|
|
11
16
|
`docs/CONSTITUTION.md` for envelope, errors, settings precedence, target
|
|
12
17
|
selection, and protocol selection. The identity/CDB **resolution depth** (lookup
|
|
@@ -19,7 +24,8 @@ README's "Status" line must agree with it.
|
|
|
19
24
|
## Verb vocabulary
|
|
20
25
|
|
|
21
26
|
Commands are centrs **verbs** (`retrieve`, `execute`, `api`, `devices`,
|
|
22
|
-
`discover`, `check`, `terminal`, `settings`), never one tool per
|
|
27
|
+
`discover`, `check`, `explain`, `terminal`, `settings`), never one tool per
|
|
28
|
+
RouterOS command. Open-ended follow
|
|
23
29
|
is folded into `api --stream` (no separate `stream` verb). Sub-verbs and their
|
|
24
30
|
aliases are canonical across CLI / API / MCP:
|
|
25
31
|
|
package/commands/api/README.md
CHANGED
|
@@ -57,24 +57,25 @@ when a bare-collection `POST` carries create-looking fields.
|
|
|
57
57
|
|
|
58
58
|
## Flags
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
60
|
+
Implemented flags are generated from the CLI metadata into
|
|
61
|
+
[`docs/CLI.md` → api](../../docs/CLI.md#api); this file does not duplicate
|
|
62
|
+
that table, and `api` has no designed-but-unimplemented flags. Behavior notes
|
|
63
|
+
the generated reference cannot carry:
|
|
64
|
+
|
|
65
|
+
- `-f` values pass through verbatim (no type-guessing); `-d`/`--input`
|
|
66
|
+
collide with `-f` → `usage/conflicting-flags`.
|
|
67
|
+
- `--query`/`--filter` map to REST `.query` words / native `?` words.
|
|
68
|
+
- `--raw-query` is emitted as-is; the caller owns the stack — e.g.
|
|
69
|
+
`--raw-query type=ether --raw-query type=vlan --raw-query '#|'` (OR).
|
|
70
|
+
- `--via rest-api --stream` errors `transport/capability-unsupported`
|
|
71
|
+
(REST's 60 s cap cannot follow).
|
|
72
|
+
- Under `--stream`, `--format json`/`yaml` emit one compact envelope per
|
|
73
|
+
line (NDJSON); `text` emits a concise row per frame.
|
|
74
|
+
- The target/auth flags (`--host`, `--port`, `--username`, `--password`,
|
|
75
|
+
`--insecure`, `--timeout`, `--cdb-file`, `--cdb-password`, `--resolve`)
|
|
76
|
+
use the same single-target resolver as `retrieve`/`execute`; `--quickchr`
|
|
77
|
+
resolves host/port/auth from the live `@tikoci/quickchr` descriptor
|
|
78
|
+
instead (constitution: resolution providers).
|
|
78
79
|
|
|
79
80
|
## Fan-out (multi-target)
|
|
80
81
|
|
package/commands/api/examples.md
CHANGED
|
@@ -426,3 +426,18 @@ The reserved record is a credential fallback, not a connectable router, so its o
|
|
|
426
426
|
target fails deterministically: inner `ok:false` with
|
|
427
427
|
`error.code=target/unresolved` (never a `transport/dns` attempt on `"__default__"`).
|
|
428
428
|
`data.summary = { total: 1, ok: 0, failed: 1 }`. Exit code 1 (every target failed).
|
|
429
|
+
|
|
430
|
+
## quickchr targets (#134)
|
|
431
|
+
|
|
432
|
+
`$NAME` is the machine name of a running quickchr-managed CHR. Host/port/auth
|
|
433
|
+
come from the live descriptor (see `commands/retrieve/examples.md` Q-series).
|
|
434
|
+
Covered by `test/integration/quickchr-target.test.ts`.
|
|
435
|
+
|
|
436
|
+
### Q1. GET against a quickchr target
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
centrs api --quickchr $NAME system/resource --json
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Envelope: `ok: true`, `data` is the resource object,
|
|
443
|
+
`meta.target.source.kind=provider`.
|
package/commands/btest/README.md
CHANGED
|
@@ -80,38 +80,27 @@ centrs btest server [--authenticate[=false]] [--user U] [--password P] \
|
|
|
80
80
|
|
|
81
81
|
## Flags
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
| Flag | RouterOS analog / default | Notes |
|
|
105
|
-
| ---- | ------------------------- | ----- |
|
|
106
|
-
| `--authenticate[=false]` | `authenticate`, **default `true`** | Require EC-SRP5 auth; `--authenticate=false` accepts anonymous clients. |
|
|
107
|
-
| `--user` / `--password` | — | The accepted credential when `authenticate=true` (v1: one user). Falls back to `CENTRS_*`. |
|
|
108
|
-
| `--bind <addr>` | **centrs-only** | Listen address; **default `127.0.0.1`**. Use `0.0.0.0` to expose on the LAN. |
|
|
109
|
-
| `--port <n>` | — (default `2000`) | Control-connection port. |
|
|
110
|
-
| `--allocate-udp-ports-from <n>` | `allocate-udp-ports-from` | Base of the UDP data-port range; default `2001` (just above the TCP/2000 control port). |
|
|
111
|
-
| `--max-sessions <n>` | `max-sessions` (1..1000), default `100` | Concurrent test cap; further clients get `routeros/btest-too-many-sessions`. |
|
|
112
|
-
| `--duration <dur>` | — | Optional auto-stop; otherwise runs until Ctrl-C. |
|
|
113
|
-
| `--format <text\|csv\|json\|yaml>` | — (default `text`) | `text` = human session log; `csv` = streaming CSV records; `json`/`yaml` = final summary envelope. |
|
|
114
|
-
| `--csv` | — | Shortcut for `--format csv`. |
|
|
83
|
+
Implemented flags are generated from the CLI metadata into
|
|
84
|
+
[`docs/CLI.md` → btest](../../docs/CLI.md#btest) — one table for both
|
|
85
|
+
subcommands, with `(client)`/`(server)` markers scoping each flag; "did you
|
|
86
|
+
mean?" hints are scoped to the active mode. This file does not duplicate that
|
|
87
|
+
table. Behavior notes the generated reference cannot carry:
|
|
88
|
+
|
|
89
|
+
- Flag names mirror the RouterOS analogs verbatim (`protocol`, `direction`,
|
|
90
|
+
`local-udp-tx-size`, `connection-count`, `authenticate`,
|
|
91
|
+
`allocate-udp-ports-from`, …); centrs-only additions are `--bind`, `--port`,
|
|
92
|
+
the shared `--format`/`--csv`, and the CDB credential flags.
|
|
93
|
+
- `--direction receive` = download (server→client), `transmit` = upload.
|
|
94
|
+
- `--connection-count` is TCP-only; **authenticated (EC-SRP5) sessions stay
|
|
95
|
+
single-stream** — the post-auth token is not captured — and emit a
|
|
96
|
+
`routeros/btest-connection-count-single-stream` warning (see Open
|
|
97
|
+
questions).
|
|
98
|
+
- `--user`/`--password` fall back to CDB / `CENTRS_*`; required when the
|
|
99
|
+
server has `authenticate=yes`. On the server they are the accepted
|
|
100
|
+
credential (v1: one user).
|
|
101
|
+
- Option ranges (`28..64000` UDP sizes, `1..255` connections, `20ms..5s`
|
|
102
|
+
interval, `1..1000` sessions) are validated before any socket opens (see
|
|
103
|
+
Errors).
|
|
115
104
|
|
|
116
105
|
## How it works
|
|
117
106
|
|
package/commands/check/README.md
CHANGED
|
@@ -197,6 +197,11 @@ triggered/enrichment checks; `--fast` suppresses progressive triggers.
|
|
|
197
197
|
|
|
198
198
|
## Flags
|
|
199
199
|
|
|
200
|
+
The whole command is spec-tier (`designed` — nothing is implemented yet), so
|
|
201
|
+
this table is the design, not a reference; once `check` lands, its
|
|
202
|
+
implemented flags will be generated into `docs/CLI.md` like every other
|
|
203
|
+
command's.
|
|
204
|
+
|
|
200
205
|
| Flag | Behavior |
|
|
201
206
|
| ---- | -------- |
|
|
202
207
|
| `--preset <name>` | `reach` / `health` (default) / `exposure` / `full`. |
|
|
@@ -243,7 +248,7 @@ RouterOS commands vary by version and arch, so a check must not blow up on a
|
|
|
243
248
|
device that lacks the path it reads. `resource` runs first and yields the **live**
|
|
244
249
|
version / arch / board; the orchestrator pre-flights each remaining check's
|
|
245
250
|
`requires` paths against that live value (falling back to the stored
|
|
246
|
-
`
|
|
251
|
+
`version` derived fact, or one batched `/console/inspect` when neither is
|
|
247
252
|
conclusive), and marks an unsupported check `ran:false` with
|
|
248
253
|
`skipReason:"unsupported-on-<version>"` — a graceful skip, not a raw protocol
|
|
249
254
|
error. Grounding is offline-first against restraml's historic `inspect.json`
|
|
@@ -53,17 +53,11 @@ tested without a router (crafted packet fixtures + a loopback socket).
|
|
|
53
53
|
|
|
54
54
|
## Flags and defaults
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
| `--port` | `5678` | UDP port to bind for MNDP. |
|
|
62
|
-
| `--cdb-file` | resolved CDB | CDB path override for `--save`. |
|
|
63
|
-
| `--cdb-password` | env/none | Decrypt an encrypted CDB; also used to re-encrypt on `--save`. |
|
|
64
|
-
| `--format` | `text` | `text`, `json`, or `yaml`; renders the same envelope. |
|
|
65
|
-
|
|
66
|
-
`--save` without `--timeout` uses the default 15s window.
|
|
56
|
+
Implemented flags (with their defaults) are generated from the CLI metadata
|
|
57
|
+
into [`docs/CLI.md` → discover](../../docs/CLI.md#discover); this file does
|
|
58
|
+
not duplicate that table. The first refresh is sent immediately, so the
|
|
59
|
+
`--timeout` listen window (default 15s) bounds the wait, and `--save` without
|
|
60
|
+
`--timeout` uses the same default window.
|
|
67
61
|
|
|
68
62
|
Bare `centrs discover` is **read-only** — it returns the envelope and never
|
|
69
63
|
writes the (WinBox-shared) CDB; `--save` is the explicit opt-in. When it finds
|