@tikoci/centrs 0.1.2 → 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 +98 -0
- package/GLOSSARY.txt +284 -0
- package/LICENSE +21 -0
- package/README.md +55 -11
- package/SECURITY.md +3 -3
- package/commands/AGENTS.md +7 -1
- package/commands/api/README.md +46 -27
- package/commands/api/examples.md +124 -6
- package/commands/btest/README.md +21 -32
- package/commands/check/README.md +376 -53
- package/commands/check/examples.md +390 -0
- package/commands/devices/README.md +177 -37
- package/commands/devices/examples.md +148 -0
- package/commands/discover/README.md +5 -11
- package/commands/execute/README.md +73 -26
- package/commands/execute/examples.md +131 -9
- package/commands/explain/README.md +1716 -0
- package/commands/explain/examples.md +606 -0
- package/commands/retrieve/README.md +55 -71
- package/commands/retrieve/examples.md +56 -9
- package/commands/settings/README.md +286 -22
- package/commands/settings/examples.md +408 -0
- package/commands/terminal/README.md +6 -0
- package/commands/transfer/README.md +57 -19
- package/commands/transfer/examples.md +95 -0
- package/docs/CLI.md +353 -0
- package/docs/CONSTITUTION.md +102 -26
- package/docs/MATRIX.md +106 -173
- package/docs/errors/README.md +5 -1
- package/docs/errors/cdb/empty-selection.md +19 -0
- package/docs/errors/input/incomplete-gps.md +9 -0
- package/docs/errors/input/invalid-altitude.md +9 -0
- package/docs/errors/input/invalid-bbox.md +9 -0
- package/docs/errors/input/invalid-coordinate.md +9 -0
- package/docs/errors/input/invalid-radius.md +9 -0
- package/docs/errors/internal/settings-failed.md +9 -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/settings/consequential-value.md +26 -0
- package/docs/errors/settings/invalid-boolean.md +21 -3
- package/docs/errors/settings/invalid-format.md +18 -3
- package/docs/errors/settings/invalid-integer.md +18 -3
- package/docs/errors/settings/invalid-timeout.md +20 -3
- package/docs/errors/settings/invalid-via.md +22 -3
- package/docs/errors/settings/reserved-key.md +29 -0
- package/docs/errors/settings/skip-env-file-active.md +25 -0
- package/docs/errors/settings/unknown-key.md +25 -0
- package/docs/errors/transport/provider-trust.md +29 -0
- package/docs/errors/usage/fanout-not-supported.md +16 -0
- package/docs/errors/usage/stdin-ignored.md +28 -0
- package/docs/errors/validation/unknown-attribute.md +37 -4
- package/package.json +49 -14
- package/src/api-fanout.ts +469 -0
- package/src/api.ts +171 -56
- package/src/cli/api.ts +156 -13
- package/src/cli/btest.ts +38 -4
- package/src/cli/common.ts +11 -0
- package/src/cli/devices.ts +235 -6
- package/src/cli/discover.ts +3 -1
- package/src/cli/execute.ts +129 -9
- package/src/cli/explain.ts +503 -0
- package/src/cli/mcp.ts +8 -1
- package/src/cli/retrieve.ts +167 -90
- package/src/cli/selection.ts +260 -0
- package/src/cli/settings.ts +286 -0
- package/src/cli/terminal.ts +22 -7
- package/src/cli/transfer.ts +192 -51
- package/src/cli.ts +22 -2
- package/src/core/envelope.ts +5 -2
- package/src/core/error-catalog.ts +95 -0
- package/src/core/fanout.ts +143 -2
- package/src/core/preflight.ts +306 -0
- package/src/core/routeros-string.ts +24 -0
- package/src/devices.ts +212 -20
- package/src/discover.ts +7 -2
- package/src/errors.ts +1 -0
- package/src/execute-fanout.ts +453 -0
- package/src/execute.ts +216 -68
- 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 +307 -1
- package/src/mcp/config.ts +12 -2
- package/src/mcp/tools.ts +137 -2
- package/src/protocols/adapter.ts +38 -18
- package/src/protocols/index.ts +11 -5
- package/src/protocols/mac-telnet-console.ts +61 -17
- package/src/resolver/cdb.ts +10 -2
- package/src/resolver/comment-kv.ts +58 -4
- package/src/resolver/config-file.ts +136 -0
- package/src/resolver/facts.ts +78 -0
- package/src/resolver/geo.ts +453 -0
- package/src/resolver/index.ts +65 -0
- package/src/resolver/mac.ts +12 -3
- package/src/resolver/quickchr-provider.ts +597 -0
- package/src/resolver/selection.ts +391 -0
- package/src/resolver/service-endpoint.ts +155 -0
- package/src/resolver/settings.ts +54 -5
- package/src/resolver/target.ts +21 -3
- package/src/retrieve-fanout.ts +239 -133
- package/src/retrieve.ts +120 -25
- package/src/settings.ts +1078 -0
- package/src/terminal.ts +11 -1
- package/src/transfer-fanout.ts +544 -0
- package/src/transfer.ts +133 -40
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,104 @@ 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
|
+
|
|
50
|
+
## 0.1.3 — 2026-07-06
|
|
51
|
+
|
|
52
|
+
Patch release. `@tikoci/centrs@0.1.3`.
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
|
|
56
|
+
- **`api` command over rest-api + native-api is `CHR-passed`.** `centrs api`
|
|
57
|
+
brings a `gh api`-style structured passthrough to both transports, and folds
|
|
58
|
+
the old standalone `stream` command into `api --stream` (native-api only,
|
|
59
|
+
`--listen` alias): a `NativeApiSession.listen()` reader with `/cancel`
|
|
60
|
+
support emits NDJSON frames plus a run summary. Grounded against real CHR
|
|
61
|
+
7.23.1.
|
|
62
|
+
- **Multi-target fan-out is uniform across `api`, `retrieve`, `execute`, and
|
|
63
|
+
`transfer`.** A shared `expandCdbSelection` + `runFanout` + `fanoutExitCode`
|
|
64
|
+
core (extracted once, consumed by all four commands) lets any command take a
|
|
65
|
+
CDB selector and run over every matching device. The positional boundary
|
|
66
|
+
that ends the selector differs per command (final positional for
|
|
67
|
+
`api`/`retrieve`, `--` for `execute`, the verb keyword for `transfer`);
|
|
68
|
+
`terminal` and `api --stream` explicitly reject `N > 1` selections since
|
|
69
|
+
neither has a sane multi-target framing.
|
|
70
|
+
- **`settings` command (`print` / `get` / `set` / `reset`).** A managed-key
|
|
71
|
+
registry for the real `CENTRS_*` environment keys backs an atomic
|
|
72
|
+
`centrs.env` writer: `set` validates per key, canonicalizes booleans to
|
|
73
|
+
`1`/`0` on disk, warns (never blocks) on consequential values
|
|
74
|
+
(`insecure=true`, `transfer-via=ftp`), and never partially writes on a
|
|
75
|
+
validation failure; `reset` deletes the managed line rather than blanking it
|
|
76
|
+
(a blank value would itself mean "set to empty" for a bash-sourced file) and
|
|
77
|
+
leaves foreign lines/comments untouched. Bare `centrs settings` behaves like
|
|
78
|
+
`print` regardless of TTY. Four new error/warning codes
|
|
79
|
+
(`settings/reserved-key`, `settings/unknown-key`,
|
|
80
|
+
`settings/consequential-value`, `settings/skip-env-file-active`) plus
|
|
81
|
+
`internal/settings-failed`, all cataloged. `CHR-passed` via 32
|
|
82
|
+
fixture-backed integration examples.
|
|
83
|
+
- **Device GPS: lat/lon/altitude storage + `--near` / `--bbox` geo
|
|
84
|
+
predicates.** `centrs devices` now stores GPS coordinates per device
|
|
85
|
+
(lat-first ordering, chosen so agents guess the field order correctly) and
|
|
86
|
+
supports proximity
|
|
87
|
+
(`--near`) and bounding-box (`--bbox`) selection predicates. `CHR-passed`
|
|
88
|
+
via fixture-backed integration coverage.
|
|
89
|
+
- **Registry⇄MATRIX drift guard + "did you mean?" flag errors.** A CI-checked
|
|
90
|
+
guard keeps the command/protocol registry and `docs/MATRIX.md` from
|
|
91
|
+
silently drifting apart; unrecognized CLI flags now suggest the closest
|
|
92
|
+
known flag instead of a bare rejection.
|
|
93
|
+
- **GitHub Pages: published API reference + error catalog.** `typedoc` output
|
|
94
|
+
and the generated error-code catalog now publish to GitHub Pages on push.
|
|
95
|
+
|
|
96
|
+
### Fixed
|
|
97
|
+
|
|
98
|
+
- **Windows unit-test portability for `settings` and MNDP.** Path-separator
|
|
99
|
+
and related platform assumptions in the `settings` and MNDP unit suites are
|
|
100
|
+
now Windows-safe (#170).
|
|
101
|
+
- **A real CodeQL-caught ReDoS in the device GPS geo-predicate parser**, fixed
|
|
102
|
+
rather than suppressed.
|
|
103
|
+
|
|
104
|
+
### Changed
|
|
105
|
+
|
|
106
|
+
- **CodeQL house-rules pack promoted to the default run**, alongside CodeRabbit
|
|
107
|
+
review-tone tuning and a reduced GitHub-checks timeout (15 → 7 minutes).
|
|
108
|
+
|
|
11
109
|
## 0.1.2 — 2026-06-26
|
|
12
110
|
|
|
13
111
|
Patch release. `@tikoci/centrs@0.1.2`.
|
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
|
|
@@ -139,6 +144,7 @@ MNDP
|
|
|
139
144
|
NAND # NAND flash memory; write-back caches file writes up to ~40s on some MikroTik boards
|
|
140
145
|
netmiko # [Multi-vendor library to simplify Paramiko SSH connections to network devices](https://github.com/ktbyers/netmiko)
|
|
141
146
|
netwatch
|
|
147
|
+
nullglob # bash shopt that makes an unmatched glob expand to zero words instead of the literal pattern
|
|
142
148
|
npk # MikroTik package format
|
|
143
149
|
nvme-over-tcp # supported by RouterOS **with** rose-storage.npk extra-package
|
|
144
150
|
OID
|
|
@@ -148,6 +154,7 @@ PRGA
|
|
|
148
154
|
proplist
|
|
149
155
|
pywinauto
|
|
150
156
|
QML
|
|
157
|
+
qll # CodeQL library file extension (.qll), e.g. CleartextLoggingCustomizations.qll
|
|
151
158
|
qmljsdebugger
|
|
152
159
|
quickchr
|
|
153
160
|
RAML
|
|
@@ -161,12 +168,16 @@ rosetta
|
|
|
161
168
|
routeros
|
|
162
169
|
routeros-skills
|
|
163
170
|
rsc # RouterOS script / export file extension (.rsc)
|
|
171
|
+
rstp # Rapid Spanning Tree Protocol; a RouterOS `protocol-mode=` value on /interface/bridge
|
|
172
|
+
SARIF # Static Analysis Results Interchange Format; CodeQL's code-scanning analysis download format
|
|
164
173
|
scp
|
|
165
174
|
scriptability
|
|
166
175
|
scriptable
|
|
176
|
+
shopt # bash builtin for toggling shell options (e.g. nullglob)
|
|
167
177
|
Sikuli
|
|
168
178
|
SikuliX
|
|
169
179
|
skillcheck
|
|
180
|
+
startswith # jq builtin filter that tests whether a string begins with a given prefix
|
|
170
181
|
SNMP
|
|
171
182
|
SPI
|
|
172
183
|
SRP
|
|
@@ -184,6 +195,7 @@ TIKOCI
|
|
|
184
195
|
tiktui
|
|
185
196
|
TLV
|
|
186
197
|
traceroute
|
|
198
|
+
tostring # jq builtin filter that renders a value as its JSON string representation
|
|
187
199
|
tsc
|
|
188
200
|
tzsp
|
|
189
201
|
TZSP
|
|
@@ -200,6 +212,7 @@ webproxy
|
|
|
200
212
|
WinAppDriver
|
|
201
213
|
winbox
|
|
202
214
|
Wireshark
|
|
215
|
+
workstream
|
|
203
216
|
workstreams
|
|
204
217
|
XCUI
|
|
205
218
|
XDG
|
|
@@ -263,6 +276,9 @@ choco
|
|
|
263
276
|
coderabbit
|
|
264
277
|
coderabbitai
|
|
265
278
|
|
|
279
|
+
# GitHub account Codex review threads are authored under (see pr-review-bots).
|
|
280
|
+
mobileskyfi
|
|
281
|
+
|
|
266
282
|
# centrs domain vocabulary
|
|
267
283
|
# %identity: the device /system/identity; a centrs CDB comment *lookup key*
|
|
268
284
|
# (`identity=`) used to resolve `<router>`. Human handle, deliberately may
|
|
@@ -364,6 +380,10 @@ CSI
|
|
|
364
380
|
SIGWINCH
|
|
365
381
|
# evl: RouterOS :parse renders a parsed command as "(evl ...)" on the console.
|
|
366
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
|
|
367
387
|
# unconfigured: a freshly-flashed RouterOS device with no IP — the mac-telnet use case.
|
|
368
388
|
unconfigured
|
|
369
389
|
unwired
|
|
@@ -391,6 +411,7 @@ Weierstrass
|
|
|
391
411
|
# ndjson: newline-delimited JSON; the stream / btest output contract (one envelope per line).
|
|
392
412
|
ndjson
|
|
393
413
|
# allocate-udp-ports-from: /tool/bandwidth-server base of the UDP data-port range.
|
|
414
|
+
allocate-udp-ports-from
|
|
394
415
|
# srp5: the "5" suffix of EC-SRP5 (the MikroTik EC-SRP variant).
|
|
395
416
|
srp5
|
|
396
417
|
# SRV: the server-endpoint test variable in commands/btest/examples.md.
|
|
@@ -434,3 +455,266 @@ toarray
|
|
|
434
455
|
# Logic shorthand ("if and only if") used in api write-gate doc comments; cspell's
|
|
435
456
|
# markdown dictionary knows it but the TypeScript one does not.
|
|
436
457
|
iff
|
|
458
|
+
|
|
459
|
+
# GitHub Pages build vocabulary (scripts/build-pages-site.ts, pages.yaml)
|
|
460
|
+
# typedoc/pandoc: the API-reference generator and the markdown->HTML converter
|
|
461
|
+
# the Pages build chains together. gfm: GitHub-Flavored Markdown, pandoc's
|
|
462
|
+
# input format for the error pages. larr: the "←" left-arrow HTML entity
|
|
463
|
+
# in the back-to-docs link. nojekyll: the marker file that disables GitHub
|
|
464
|
+
# Pages' Jekyll processing for an Actions-deployed artifact. extensionless:
|
|
465
|
+
# describes the `details_url` contract (docs/errors/README.md) — no `.html`.
|
|
466
|
+
typedoc
|
|
467
|
+
pandoc
|
|
468
|
+
gfm
|
|
469
|
+
larr
|
|
470
|
+
nojekyll
|
|
471
|
+
extensionless
|
|
472
|
+
# nothrow: Bun Shell's `$` method to disable throwing on a non-zero exit
|
|
473
|
+
# (scripts/agent-check.ts), so the caller can inspect output either way.
|
|
474
|
+
nothrow
|
|
475
|
+
|
|
476
|
+
# check-command spec vocabulary (commands/check/README.md, examples.md)
|
|
477
|
+
# TikTOML: centrs-owned readable device-inventory format (#137); check's
|
|
478
|
+
# metadata feeds it. routerboard: RouterBOARD firmware/hardware menu
|
|
479
|
+
# (/system/routerboard). rscmd: the tikbook RouterOS command-notebook file
|
|
480
|
+
# extension (.rscmd), the format the check spec was grounded against.
|
|
481
|
+
TikTOML
|
|
482
|
+
routerboard
|
|
483
|
+
rscmd
|
|
484
|
+
# RTT: round-trip time, the host->router connect-latency reach signal. tojson: the
|
|
485
|
+
# /system/script helper (:serialize to=json) the batched execute reads reuse.
|
|
486
|
+
# qrcode: the /ip/cloud vpn-wireguard-client-config-qrcode field token (redacted
|
|
487
|
+
# by the cloud check, referenced when documenting redaction).
|
|
488
|
+
RTT
|
|
489
|
+
tojson
|
|
490
|
+
qrcode
|
|
491
|
+
|
|
492
|
+
# Device GPS vocabulary (issue #146, commands/devices/README.md "Location /
|
|
493
|
+
# GPS", src/resolver/geo.ts). MSL/AGL: the two supported altitude-type vertical
|
|
494
|
+
# datums (mean sea level / above ground level); stored case-insensitively but
|
|
495
|
+
# normalized to upper case. EPSG: the geodetic coordinate-reference-system
|
|
496
|
+
# registry (EPSG:4326 = WGS84 lat/lon), cited for the lat-first ordering
|
|
497
|
+
# rationale. bbox: the --bbox geo selector (bounding box). wgs: WGS84, the
|
|
498
|
+
# geodetic datum GPS coordinates use; appears only as a deliberately-invalid
|
|
499
|
+
# --altitude-type value in tests/examples. antimeridian: the 180° meridian a
|
|
500
|
+
# --bbox may not cross in v1. GEOSEARCH: the Redis command whose m/km/mi/ft
|
|
501
|
+
# radius-unit vocabulary --near borrows. IUGG: the geodesy union whose mean
|
|
502
|
+
# Earth radius the haversine uses. SFO/OAK: airports used as a known-distance
|
|
503
|
+
# haversine fixture in tests. ele/GPX: `ele` is GPX's altitude element, kept as
|
|
504
|
+
# an input alias for `altitude` (GPX = the GPS Exchange Format). Geolocation:
|
|
505
|
+
# the W3C Geolocation API, cited (with ISO 6709 / EPSG / IETF geo:) for why
|
|
506
|
+
# `altitude` — not `elevation` — is the canonical field name.
|
|
507
|
+
MSL
|
|
508
|
+
msl
|
|
509
|
+
AGL
|
|
510
|
+
agl
|
|
511
|
+
Agl
|
|
512
|
+
EPSG
|
|
513
|
+
bbox
|
|
514
|
+
wgs
|
|
515
|
+
antimeridian
|
|
516
|
+
GEOSEARCH
|
|
517
|
+
IUGG
|
|
518
|
+
SFO
|
|
519
|
+
sfo
|
|
520
|
+
ele
|
|
521
|
+
GPX
|
|
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,6 +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 try the current offline analyzer without
|
|
8
|
+
installing centrs or connecting to a router:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
bunx @tikoci/centrs@next explain '/ip/address print' --json
|
|
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
|
+
|
|
7
22
|
It is a **friendly conduit**, not a high-level configuration abstraction. It
|
|
8
23
|
helps humans and agents reach RouterOS over the right protocol, with the right
|
|
9
24
|
credentials and ports, and validates RouterOS-shaped commands before running
|
|
@@ -11,9 +26,15 @@ them. It does **not** hide RouterOS behind helpers like `createVlanOnBridge()`
|
|
|
11
26
|
— you still speak RouterOS. Validation and structured diagnostics are the
|
|
12
27
|
product; without them this would just be a worse `curl`.
|
|
13
28
|
|
|
14
|
-
> **Status:** early
|
|
15
|
-
>
|
|
16
|
-
>
|
|
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
|
|
35
|
+
> `npm view @tikoci/centrs dist-tags --json`. The library, device registry, and
|
|
36
|
+
> first MCP server phases are CHR-verified; the CLI is wired (`coded`);
|
|
37
|
+
> encrypted-CDB writes are still blocked, and the TUI/proxy frontends are planned.
|
|
17
38
|
> `docs/MATRIX.md` is the single source of truth for what works today — treat
|
|
18
39
|
> anything not green there as not-yet-shipped.
|
|
19
40
|
|
|
@@ -26,8 +47,10 @@ product; without them this would just be a worse `curl`.
|
|
|
26
47
|
SSH / MAC-Telnet / RoMON / WinBox Terminal for interactive and L2 execute;
|
|
27
48
|
MNDP for discovery. centrs picks the protocol for you (and lets you pin one
|
|
28
49
|
with `via=` or `--via`).
|
|
29
|
-
- **Commands:** every command resolves a *target* — a router you
|
|
30
|
-
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.)
|
|
31
54
|
|
|
32
55
|
| Command | Purpose |
|
|
33
56
|
| ---------- | ------- |
|
|
@@ -36,6 +59,7 @@ product; without them this would just be a worse `curl`.
|
|
|
36
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). |
|
|
37
60
|
| `terminal` | Open an interactive console, primarily SSH or MAC-Telnet. |
|
|
38
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. |
|
|
39
63
|
| `devices` | View and maintain the CDB-backed device registry (the only writer). |
|
|
40
64
|
| `discover` | Discover MNDP neighbors and optionally save them into the CDB. |
|
|
41
65
|
| `settings` | Manage centrs's own settings (`centrs.env`, `__default__`) and run first-time setup. |
|
|
@@ -104,16 +128,23 @@ CDB tags, and `devices set` refuses to put them there. Unknown keys produce a
|
|
|
104
128
|
`cdb/unknown-option` warning and are ignored, so a stray `=` in human prose
|
|
105
129
|
never breaks anything.
|
|
106
130
|
|
|
107
|
-
Settings resolve lowest-to-highest: **built-in defaults →
|
|
108
|
-
comment-kv → `CENTRS_*` env → CLI flag / API arg.** Every
|
|
109
|
-
reports which source won each setting under `meta.settings`,
|
|
110
|
-
see *why* a given port or transport was chosen.
|
|
131
|
+
Settings resolve lowest-to-highest: **built-in defaults → user config file
|
|
132
|
+
(`centrs.env`) → comment-kv → `CENTRS_*` env → CLI flag / API arg.** Every
|
|
133
|
+
result envelope reports which source won each setting under `meta.settings`,
|
|
134
|
+
so you can always see *why* a given port or transport was chosen.
|
|
111
135
|
|
|
112
136
|
### Groups, discovery, and the MCP allowlist all ride on the CDB
|
|
113
137
|
|
|
114
138
|
- **Groups** are CDB-native: an entry's `group` field is just a string, and
|
|
115
139
|
`--group prod-edge` fans a single command out to every entry that shares it.
|
|
116
|
-
There is no separate group-definition file.
|
|
140
|
+
There is no separate group-definition file. Groups are one selector in a
|
|
141
|
+
**uniform fan-out grammar** shared by `api`, `retrieve`, `execute`, and
|
|
142
|
+
`transfer`: mix `<router>` positionals, repeatable `--group`/`--where
|
|
143
|
+
<attr>=<value>`, `--all`, and `--default` (de-duped by CDB record index). Every
|
|
144
|
+
fan-out returns the locked `FanoutData` envelope (per-target results, not
|
|
145
|
+
metadata) with a granular exit code (`0` all ok / `2` partial / `1` all failed);
|
|
146
|
+
a multi-target write is gated once by `--yes` naming the blast radius. See
|
|
147
|
+
`docs/CONSTITUTION.md` (Target selection grammar).
|
|
117
148
|
- **Discovery** writes back into the CDB: `discover --save` records MNDP
|
|
118
149
|
neighbors as new entries tagged `group=discovered` with a `source=mndp`
|
|
119
150
|
marker — hints to curate, not authoritative inventory.
|
|
@@ -168,7 +199,7 @@ roadmap.
|
|
|
168
199
|
|
|
169
200
|
Requirements:
|
|
170
201
|
|
|
171
|
-
- 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).
|
|
172
203
|
- Git.
|
|
173
204
|
- For integration tests: QEMU plus `@tikoci/quickchr` (handles CHR image
|
|
174
205
|
download and boot).
|
|
@@ -188,6 +219,19 @@ Generated API docs through TypeDoc:
|
|
|
188
219
|
bun run build:doc:api
|
|
189
220
|
```
|
|
190
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
|
+
|
|
191
235
|
## Done definition (short version)
|
|
192
236
|
|
|
193
237
|
A feature is done when every line in `commands/<name>/examples.md` is green on
|
package/SECURITY.md
CHANGED
|
@@ -14,14 +14,14 @@ Please include the affected files or workflow, reproduction details, and impact.
|
|
|
14
14
|
|
|
15
15
|
The repository's [Security tab](https://github.com/tikoci/centrs/security) is the live source of current alerts and advisories. This section describes *what* checks run and *why*, so the doc stays meaningful even when the badge is at 0.
|
|
16
16
|
|
|
17
|
-
- **CodeQL** — repo-managed workflow at [`.github/workflows/codeql.yaml`](.github/workflows/codeql.yaml) with config [`.github/codeql-config.yml`](.github/codeql-config.yml). Query suite: `security-and-quality` (security-extended + code-quality). Languages: `javascript-typescript`, `actions`. Schedule: push to `main`, pull requests to `main`, weekly cron, and manual dispatch.
|
|
18
|
-
- **Code Quality (AI findings, preview)** —
|
|
17
|
+
- **CodeQL** — repo-managed workflow at [`.github/workflows/codeql.yaml`](.github/workflows/codeql.yaml) with config [`.github/codeql-config.yml`](.github/codeql-config.yml). Query suite: `security-and-quality` (security-extended + code-quality) plus a small custom pack, [`.github/codeql-house-rules/`](.github/codeql-house-rules/), that structurally checks a handful of repo-specific invariants (currently: `apiFanout` must call its named protocol/validation gates) — see `.github/instructions/github-security-quality.instructions.md` for scope and the verify-before-promote discipline for adding more rules there. Languages: `javascript-typescript`, `actions`. Schedule: push to `main`, pull requests to `main`, weekly cron, and manual dispatch.
|
|
18
|
+
- **Code Quality (AI findings, preview)** — confirmed active in GitHub as of 2026-07-03 (not just "intended"; see [issue #166](https://github.com/tikoci/centrs/issues/166)). [`.github/workflows/codeql.yaml`](.github/workflows/codeql.yaml) includes a non-failing forward-compat probe for a future AI-findings API. AI findings are noisy and self-contradicting; we accept the noise because the second-opinion catches real issues that the static suite misses. Steady-state goal is 0 open findings. False positives are dismissed via the GitHub UI with a written justification — that text is the audit-log contract. Side effect: GitHub's own Code Quality scan runs in parallel with our Advanced Setup and posts a same-named `Analyze (javascript-typescript)` check, so PR checks lists show it twice — cosmetic, tracked in #166, not a required check either way (see issue #118).
|
|
19
19
|
- **Dependency review** — not enabled. GitHub dependency review follows dependency-graph ecosystem support, and this Bun-only repository currently does not have a supported lockfile for that gate.
|
|
20
20
|
- **Dependabot security updates** — enabled and configured in [`.github/dependabot.yaml`](.github/dependabot.yaml).
|
|
21
21
|
- **Secret scanning** — enabled in GitHub, with push protection.
|
|
22
22
|
- **Private vulnerability reporting** — enabled via GitHub Security Advisories.
|
|
23
23
|
|
|
24
|
-
Some GitHub Security tab data, especially Code Quality AI findings, is not
|
|
24
|
+
Some GitHub Security tab data, especially Code Quality AI findings, is not reachable through the default workflow `GITHUB_TOKEN` (`repos/{owner}/{repo}/code-quality/findings` 403s there even with `security-events: read`) — it does respond with an elevated/owner-scoped token, but no findings have been recorded yet to confirm the response shape end-to-end (see #166). Human review in the GitHub UI remains part of the security workflow until that's wired up.
|
|
25
25
|
|
|
26
26
|
## Supported versions
|
|
27
27
|
|
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
|
|