@horizon36596/zenith-mcp 0.1.1
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/LICENSE +21 -0
- package/NOTICE +18 -0
- package/README.md +129 -0
- package/dist/editIo.d.ts +15 -0
- package/dist/editIo.d.ts.map +1 -0
- package/dist/editIo.js +33 -0
- package/dist/editIo.js.map +1 -0
- package/dist/findings.d.ts +35 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +76 -0
- package/dist/findings.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/project.d.ts +46 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +106 -0
- package/dist/project.js.map +1 -0
- package/dist/resources.d.ts +3 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +37 -0
- package/dist/resources.js.map +1 -0
- package/dist/result.d.ts +14 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +27 -0
- package/dist/result.js.map +1 -0
- package/dist/schemas.d.ts +576 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +197 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +27 -0
- package/dist/server.js.map +1 -0
- package/dist/spawnCli.d.ts +28 -0
- package/dist/spawnCli.d.ts.map +1 -0
- package/dist/spawnCli.js +57 -0
- package/dist/spawnCli.js.map +1 -0
- package/dist/tools/analysis.d.ts +4 -0
- package/dist/tools/analysis.d.ts.map +1 -0
- package/dist/tools/analysis.js +128 -0
- package/dist/tools/analysis.js.map +1 -0
- package/dist/tools/auto.d.ts +4 -0
- package/dist/tools/auto.d.ts.map +1 -0
- package/dist/tools/auto.js +43 -0
- package/dist/tools/auto.js.map +1 -0
- package/dist/tools/edit.d.ts +3 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +346 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/project.d.ts +4 -0
- package/dist/tools/project.d.ts.map +1 -0
- package/dist/tools/project.js +58 -0
- package/dist/tools/project.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -0
- package/package.json +67 -0
- package/spec/checks.md +313 -0
- package/spec/file-format.md +672 -0
package/spec/checks.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Checks and findings
|
|
2
|
+
|
|
3
|
+
Zenith checks every auto each time it changes. Each problem it finds is a **finding**: a code, a
|
|
4
|
+
severity, the step it belongs to, and a message. Where it can, a finding also says where along the
|
|
5
|
+
path it happened, and the editor marks that spot on the field.
|
|
6
|
+
|
|
7
|
+
The editor, the CLI and the MCP server run the same checks on the same files, so they always agree.
|
|
8
|
+
|
|
9
|
+
## Severities
|
|
10
|
+
|
|
11
|
+
| severity | meaning |
|
|
12
|
+
|---|---|
|
|
13
|
+
| **error** | The auto is wrong: the robot would refuse the file, crash, break a rule or run out of time. `zenith validate` exits non-zero on any error. |
|
|
14
|
+
| **warning** | The auto will run, but probably not the way you want. Fix it or accept it knowingly. |
|
|
15
|
+
| **info** | Something worth knowing. Nothing needs to change. |
|
|
16
|
+
|
|
17
|
+
## Reading findings
|
|
18
|
+
|
|
19
|
+
In the editor, click a finding's code chip to see what it means and how to fix it. Some findings
|
|
20
|
+
have a one-click fix.
|
|
21
|
+
|
|
22
|
+
On the command line, `--explain` prints the same help under each finding:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
zenith validate autos/first-auto.auto.json --explain
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`--json` prints the findings as JSON for scripts and agents.
|
|
29
|
+
|
|
30
|
+
## All codes
|
|
31
|
+
|
|
32
|
+
| code | severity | what it means |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| [`SCHEMA`](#schema) | error | Something in a file is not allowed: a misspelled command, a missing value, a waypoint that does not exist. |
|
|
35
|
+
| [`CONTINUITY`](#continuity) | error | A path starts somewhere other than where the robot is. |
|
|
36
|
+
| [`HEADING_MISSING`](#heading_missing) | error | A path does not say which way the robot faces. |
|
|
37
|
+
| [`HEADING`](#heading) | warning or info | The robot will not face the way this path asks. |
|
|
38
|
+
| [`HEADING_RANGES`](#heading_ranges) | error | A piecewise heading's ranges do not cover the path from 0 to 1. |
|
|
39
|
+
| [`PERIMETER`](#perimeter) | error | Part of the robot would go past the field wall. |
|
|
40
|
+
| [`STRUCTURE`](#structure) | error | The robot's outline overlaps something solid on the field. |
|
|
41
|
+
| [`KEEPOUT`](#keepout) | warning | The robot drives into a zone the rules restrict during auto. |
|
|
42
|
+
| [`START_ILLEGAL`](#start_illegal) | error | The starting pose breaks a game rule. |
|
|
43
|
+
| [`LEGAL_APPROACH`](#legal_approach) | error | The robot shoots from a place the rules do not allow for its target. |
|
|
44
|
+
| [`TURRET_RANGE`](#turret_range) | warning | The turret cannot turn far enough to aim at the target. |
|
|
45
|
+
| [`CAPACITY`](#capacity) | error | The robot would hold more pieces than it can carry or the rules allow. |
|
|
46
|
+
| [`EMPTY_SHOT`](#empty_shot) | warning | A shoot step runs with nothing, or too little, to shoot. |
|
|
47
|
+
| [`STRAFE_FRACTION`](#strafe_fraction) | warning | Much of a path is driven sideways, which is slow on mecanum. |
|
|
48
|
+
| [`MOUTH_LEADING`](#mouth_leading) | warning | The intake is running but not facing the way the robot drives. |
|
|
49
|
+
| [`SWEEP_SPEED`](#sweep_speed) | warning | The robot drives too fast while its intake runs. |
|
|
50
|
+
| [`TIME_BUDGET`](#time_budget) | error, warning or info | The routine may not fit in the autonomous period. |
|
|
51
|
+
| [`TIMEOUT_TIGHT`](#timeout_tight) | info | A step's timeout is close to how long it should take. |
|
|
52
|
+
| [`STATIONARY_MARKER`](#stationary_marker) | warning | A stand-still command is set to fire while the robot moves. |
|
|
53
|
+
| [`MOVES_ROBOT`](#moves_robot) | error | A path assumes a fixed start after a command that moves the robot by itself. |
|
|
54
|
+
| [`PROVENANCE`](#provenance) | info | A pose has no note saying where its numbers came from. |
|
|
55
|
+
|
|
56
|
+
## Codes in detail
|
|
57
|
+
|
|
58
|
+
### `SCHEMA`
|
|
59
|
+
|
|
60
|
+
**File problem.** Error.
|
|
61
|
+
|
|
62
|
+
Something in the file is not allowed. The robot would refuse to load it. This covers:
|
|
63
|
+
|
|
64
|
+
- the file does not match its [JSON Schema](file-format.md#json-schemas);
|
|
65
|
+
- a command or condition name that `robot.json` does not list, or arguments that do not fit the
|
|
66
|
+
command's `params`;
|
|
67
|
+
- a `{ "ref": ... }` to a waypoint that `waypoints.json` does not have;
|
|
68
|
+
- a `wait` with both `seconds` and `until`, or with neither;
|
|
69
|
+
- a `parallel` group in `deadline` mode whose `deadline` names none of its own direct members.
|
|
70
|
+
|
|
71
|
+
**Fix.** Read the message for the exact key that is wrong. Pick the name from the list the editor
|
|
72
|
+
offers, or add the missing value.
|
|
73
|
+
|
|
74
|
+
### `CONTINUITY`
|
|
75
|
+
|
|
76
|
+
**Path jumps.** Error.
|
|
77
|
+
|
|
78
|
+
A path starts somewhere other than where the robot is, so the robot would have to teleport. The
|
|
79
|
+
gap is measured from where the previous step ended, and anything over 0.5 in counts. Segments
|
|
80
|
+
inside one path must also meet within 0.5 in.
|
|
81
|
+
|
|
82
|
+
How "where the previous step ended" is worked out:
|
|
83
|
+
|
|
84
|
+
- a `sequence` chains its members like the top-level list;
|
|
85
|
+
- every member of a `parallel` group starts where the group started;
|
|
86
|
+
- the first step of each side of a `branch` starts where the branch started;
|
|
87
|
+
- `"from": "current"` is only allowed after a step that defines where the robot is.
|
|
88
|
+
|
|
89
|
+
**Fix.** Set the path's start to `"current"` so it begins wherever the robot is. Or drag its first
|
|
90
|
+
point onto the end of the step before it.
|
|
91
|
+
|
|
92
|
+
### `HEADING_MISSING`
|
|
93
|
+
|
|
94
|
+
**No heading.** Error.
|
|
95
|
+
|
|
96
|
+
A path does not say which way the robot should face while it drives. Pedro, the path follower,
|
|
97
|
+
stops the auto with an error when a path has no heading.
|
|
98
|
+
|
|
99
|
+
**Fix.** Choose a heading mode in the path's inspector. `tangent`, which points the nose along the
|
|
100
|
+
path, is the usual choice.
|
|
101
|
+
|
|
102
|
+
### `HEADING`
|
|
103
|
+
|
|
104
|
+
**Heading differs on the robot.** Warning or info.
|
|
105
|
+
|
|
106
|
+
The robot will not face the way this path asks. Two cases:
|
|
107
|
+
|
|
108
|
+
- **Warning:** a `linear` heading turns more than half a circle on one segment. Pedro turns each
|
|
109
|
+
segment's share of the sweep the short way round, so the robot goes the other way. The message
|
|
110
|
+
gives the turn the robot actually makes, in degrees, counter-clockwise positive.
|
|
111
|
+
- **Info:** a `facePoint` heading has a non-zero `offsetRad`. The robot runtime ignores the offset
|
|
112
|
+
for now. The editor still draws it.
|
|
113
|
+
|
|
114
|
+
Both apply inside a [`piecewise`](file-format.md#piecewise-heading) heading too, to a `linear` or
|
|
115
|
+
`facePoint` range; the finding's `t` is where the range starts.
|
|
116
|
+
|
|
117
|
+
**Fix.** Split the path so no piece turns more than half a circle, or set the heading at a waypoint
|
|
118
|
+
in between. For the info, set `offsetRad` to 0 or accept that the robot will face the point
|
|
119
|
+
directly.
|
|
120
|
+
|
|
121
|
+
### `HEADING_RANGES`
|
|
122
|
+
|
|
123
|
+
**Heading ranges do not fit.** Error.
|
|
124
|
+
|
|
125
|
+
A [`piecewise`](file-format.md#piecewise-heading) heading must split its path into ranges that run
|
|
126
|
+
from `t` 0 to `t` 1 in order: the first starts at 0, each starts where the one before it ends, each
|
|
127
|
+
ends after it starts, and the last ends at 1. Pedro's piecewise interpolator stops the auto on the
|
|
128
|
+
robot when they do not, so the file cannot run. The message names the first range that is wrong and
|
|
129
|
+
how.
|
|
130
|
+
|
|
131
|
+
**Fix.** Drag the boundaries in the inspector's range track, or set each range's end, so each range
|
|
132
|
+
starts where the one before it ends. The editor's own range edits never leave a gap or an overlap;
|
|
133
|
+
this finding means the file was edited by hand.
|
|
134
|
+
|
|
135
|
+
### `PERIMETER`
|
|
136
|
+
|
|
137
|
+
**Leaves the field.** Error.
|
|
138
|
+
|
|
139
|
+
Part of the robot, its body or an intake mouth, would go past the field wall at some point on the
|
|
140
|
+
path. A real robot would hit the wall instead. The check uses the robot's expanded footprint,
|
|
141
|
+
turned to its heading, plus every mouth.
|
|
142
|
+
|
|
143
|
+
**Fix.** Move the point away from the wall until the outline stays inside. Snapping to the wall
|
|
144
|
+
places the robot flush against it and never raises this finding.
|
|
145
|
+
|
|
146
|
+
### `STRUCTURE`
|
|
147
|
+
|
|
148
|
+
**Hits a field element.** Error.
|
|
149
|
+
|
|
150
|
+
The robot's outline overlaps an obstacle marked `solidToRobot` in the field file, such as the hive
|
|
151
|
+
or a flower base. The robot would crash into it. Only obstacles that reach below the robot's height
|
|
152
|
+
count, so the robot can drive under a bar that is higher than it is. The footprint is checked every
|
|
153
|
+
2 in along the path and at every segment end, mouths included. The finding names the obstacle and
|
|
154
|
+
marks where the overlap is deepest.
|
|
155
|
+
|
|
156
|
+
**Fix.** Move the path around the element, or add a point to bend it clear.
|
|
157
|
+
|
|
158
|
+
### `KEEPOUT`
|
|
159
|
+
|
|
160
|
+
**Enters a no-go zone.** Warning.
|
|
161
|
+
|
|
162
|
+
The robot drives into a zone the game rules restrict during the autonomous period. That can cost a
|
|
163
|
+
penalty. Only zones marked `appliesInAuto: true` in the field file count.
|
|
164
|
+
|
|
165
|
+
**Fix.** Reroute the path so the outline stays out of the shaded zone. The zone's rule is named in
|
|
166
|
+
the message.
|
|
167
|
+
|
|
168
|
+
### `START_ILLEGAL`
|
|
169
|
+
|
|
170
|
+
**Start not allowed.** Error.
|
|
171
|
+
|
|
172
|
+
The starting pose breaks a rule in the field's `startRules`: not touching a wall, starting in the
|
|
173
|
+
wrong half, starting in a loading zone, or touching a flower. The referees would not let the match
|
|
174
|
+
start like this.
|
|
175
|
+
|
|
176
|
+
**Fix.** Drag the start pose to a legal spot, usually flush against your own alliance's wall. Wall
|
|
177
|
+
snap helps.
|
|
178
|
+
|
|
179
|
+
### `LEGAL_APPROACH`
|
|
180
|
+
|
|
181
|
+
**Shot from an illegal spot.** Error.
|
|
182
|
+
|
|
183
|
+
A command that launches pieces (one with `ledger.launches` in `robot.json`) runs where the target is
|
|
184
|
+
not legally approachable. For a BIOBUZZ hive cell, the robot must be outboard of the up cell's outer
|
|
185
|
+
face by the margin the field file gives, on the correct side. The scoring would not count or would
|
|
186
|
+
draw a penalty.
|
|
187
|
+
|
|
188
|
+
**Fix.** Move the shooting pose to the allowed side of the target. The one-click fix moves it to the
|
|
189
|
+
nearest legal spot.
|
|
190
|
+
|
|
191
|
+
### `TURRET_RANGE`
|
|
192
|
+
|
|
193
|
+
**Turret cannot aim.** Warning.
|
|
194
|
+
|
|
195
|
+
At this shooting pose, the bearing to the target relative to the chassis is outside the turret's
|
|
196
|
+
`turretRangeRad` in `robot.json`. The robot would shoot in the wrong direction. Robots with no
|
|
197
|
+
turret never raise it.
|
|
198
|
+
|
|
199
|
+
**Fix.** Turn the robot so the target is closer to straight ahead, or move the shooting pose.
|
|
200
|
+
|
|
201
|
+
### `CAPACITY`
|
|
202
|
+
|
|
203
|
+
**Holds too many.** Error.
|
|
204
|
+
|
|
205
|
+
The ledger says the robot would hold more pieces than `capacity.max` in `robot.json`, either at the
|
|
206
|
+
start or after a collect. Something would fall out or draw a penalty.
|
|
207
|
+
|
|
208
|
+
**Fix.** Shoot or drop pieces before collecting more, or collect fewer. The ledger panel shows what
|
|
209
|
+
the robot holds after each step.
|
|
210
|
+
|
|
211
|
+
### `EMPTY_SHOT`
|
|
212
|
+
|
|
213
|
+
**Shooting nothing.** Warning.
|
|
214
|
+
|
|
215
|
+
A shoot step runs when the ledger says the robot holds nothing, or fewer pieces than the step
|
|
216
|
+
launches. It wastes time in the autonomous period.
|
|
217
|
+
|
|
218
|
+
**Fix.** Collect before shooting, or remove the shot. Check the ledger panel to see when the robot
|
|
219
|
+
is empty.
|
|
220
|
+
|
|
221
|
+
### `STRAFE_FRACTION`
|
|
222
|
+
|
|
223
|
+
**Driving sideways.** Warning.
|
|
224
|
+
|
|
225
|
+
Too much of this path is driven sideways: the distance where the travel direction is closer to the
|
|
226
|
+
robot's side than to its nose is over the threshold (20 % by default, set by `strafeFractionWarn` in
|
|
227
|
+
`robot.json`). On mecanum wheels, sideways driving is slower and stops less sharply than driving
|
|
228
|
+
forward. The message says how many seconds it costs against driving the same leg nose-first.
|
|
229
|
+
|
|
230
|
+
**Fix.** Use the fix that points the nose along the path, or turn during the previous stop. Keep
|
|
231
|
+
sideways driving for short, deliberate moves, such as a sweep along a wall.
|
|
232
|
+
|
|
233
|
+
### `MOUTH_LEADING`
|
|
234
|
+
|
|
235
|
+
**Intake not in front.** Warning.
|
|
236
|
+
|
|
237
|
+
An intake is running on this path, but its mouth is more than 30° away from the direction the robot
|
|
238
|
+
drives. The robot's body would push game pieces away instead of picking them up. The intake counts
|
|
239
|
+
as running when a marker turns it on, when an earlier `intakeOn` was never stopped, or when an
|
|
240
|
+
`intakeOn` runs in another member of the same `parallel` group.
|
|
241
|
+
|
|
242
|
+
**Fix.** Choose a heading that puts the running mouth in front: `tangent` for a front mouth,
|
|
243
|
+
`tangentReversed` for a back one.
|
|
244
|
+
|
|
245
|
+
### `SWEEP_SPEED`
|
|
246
|
+
|
|
247
|
+
**Intaking too fast.** Warning.
|
|
248
|
+
|
|
249
|
+
The robot drives faster than `sweepSpeedFraction` in `robot.json` (0.4 by default) while its intake
|
|
250
|
+
runs. Pieces get knocked away rather than collected at that speed.
|
|
251
|
+
|
|
252
|
+
**Fix.** Lower this path's `speedFraction` to the sweep speed. The one-click fix does it for you.
|
|
253
|
+
|
|
254
|
+
### `TIME_BUDGET`
|
|
255
|
+
|
|
256
|
+
**Over the time limit.** Error, warning or info.
|
|
257
|
+
|
|
258
|
+
The whole routine may take longer than the autonomous period (`periods.autoS` in the field file).
|
|
259
|
+
Anything after the buzzer does not happen. The estimate is a range, and the severity depends on
|
|
260
|
+
which end of it is over:
|
|
261
|
+
|
|
262
|
+
- **Error:** even the optimistic end of the range is over the period.
|
|
263
|
+
- **Warning:** the nominal estimate is over; only the optimistic end fits.
|
|
264
|
+
- **Info:** the routine fits, but some step has no fixed time. Either a step has no estimate at
|
|
265
|
+
all, so the total is a lower bound, or a step ends on a condition, so the total is an upper bound.
|
|
266
|
+
|
|
267
|
+
**Fix.** Cut or shorten steps, drive faster where it is safe, or move slow steps later. The timeline
|
|
268
|
+
shows which steps take the longest.
|
|
269
|
+
|
|
270
|
+
### `TIMEOUT_TIGHT`
|
|
271
|
+
|
|
272
|
+
**Timeout too short.** Info.
|
|
273
|
+
|
|
274
|
+
This step's `timeoutS` is under 1.2 times its estimate. A slightly slow run would be cut off before
|
|
275
|
+
it finishes.
|
|
276
|
+
|
|
277
|
+
**Fix.** Raise the step's timeout to a little more than its estimate. The estimate is shown beside
|
|
278
|
+
the step.
|
|
279
|
+
|
|
280
|
+
### `STATIONARY_MARKER`
|
|
281
|
+
|
|
282
|
+
**Stop-only command while moving.** Warning.
|
|
283
|
+
|
|
284
|
+
A marker fires a command that `robot.json` marks `stationary: true`, in the middle of a path. It
|
|
285
|
+
would run while the robot is still driving.
|
|
286
|
+
|
|
287
|
+
**Fix.** Make it its own `command` step after the path instead of a marker on it.
|
|
288
|
+
|
|
289
|
+
### `MOVES_ROBOT`
|
|
290
|
+
|
|
291
|
+
**Start after a moving command.** Error.
|
|
292
|
+
|
|
293
|
+
The step before this one runs a command marked `movesRobot: true`, which drives the robot by itself,
|
|
294
|
+
so nobody knows exactly where it ends. This path starts from a fixed pose anyway.
|
|
295
|
+
|
|
296
|
+
**Fix.** Set this path's start to `"current"` so it begins wherever the robot really is.
|
|
297
|
+
|
|
298
|
+
### `PROVENANCE`
|
|
299
|
+
|
|
300
|
+
**Where did this come from?** Info.
|
|
301
|
+
|
|
302
|
+
A pose has no provenance label saying where its numbers came from, such as measured on the field or
|
|
303
|
+
set in the editor. Inline poses the editor writes are treated as `SET FROM EDITOR`. This is only a
|
|
304
|
+
reminder, not an error. See [provenance labels](file-format.md#provenance-labels).
|
|
305
|
+
|
|
306
|
+
**Fix.** Nothing is required. Measure the pose on the field, or save it as a named waypoint with a
|
|
307
|
+
label, to record where it came from.
|
|
308
|
+
|
|
309
|
+
## Checks that need an estimate
|
|
310
|
+
|
|
311
|
+
`STRAFE_FRACTION`, `TIME_BUDGET` and `TIMEOUT_TIGHT` use the time estimate. If an estimate cannot be
|
|
312
|
+
made, those three are skipped and every other check still runs. See [Simulation](simulation.md) for
|
|
313
|
+
how the estimate is made.
|