dsh-model-everything 0.1.0 → 0.3.0
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/README.en-US.md +102 -81
- package/README.md +88 -76
- package/lib/automaton-tool.js +69 -0
- package/lib/automaton.js +327 -0
- package/lib/compose-tool.js +11 -2
- package/lib/concurrency-tool.js +6 -1
- package/lib/data-engine.js +1 -1
- package/lib/data-tool.js +18 -5
- package/lib/design-tool.js +21 -8
- package/lib/edit-tool.js +111 -0
- package/lib/editor.js +293 -0
- package/lib/engine.js +8 -1
- package/lib/export-tool.js +6 -1
- package/lib/index.js +4 -0
- package/lib/model-file.js +48 -0
- package/lib/presentation.js +81 -0
- package/lib/report-diff-tool.js +6 -1
- package/lib/report-view.js +92 -15
- package/lib/routing.js +85 -0
- package/lib/scan.js +547 -0
- package/lib/structure-tool.js +34 -1
- package/lib/structure.js +28 -3
- package/lib/tool.js +19 -4
- package/lib/types/automaton-tool.d.ts +2 -0
- package/lib/types/automaton.d.ts +57 -0
- package/lib/types/edit-tool.d.ts +2 -0
- package/lib/types/editor.d.ts +46 -0
- package/lib/types/engine.d.ts +1 -0
- package/lib/types/model-file.d.ts +7 -0
- package/lib/types/presentation.d.ts +59 -0
- package/lib/types/report-view.d.ts +8 -1
- package/lib/types/routing.d.ts +31 -0
- package/lib/types/scan.d.ts +37 -0
- package/lib/types/structure.d.ts +16 -0
- package/lib/uml-tool.js +16 -6
- package/package.json +8 -3
- package/skills/model-everything/SKILL.md +51 -79
- package/skills/model-everything/references/automata.md +102 -0
- package/skills/model-everything-interleaving/SKILL.zh-CN.md +60 -60
- package/skills/model-everything-report-reading/SKILL.md +137 -137
- package/src/automaton-tool.ts +73 -0
- package/src/automaton.ts +375 -0
- package/src/compose-tool.ts +13 -3
- package/src/concurrency-tool.ts +7 -1
- package/src/data-engine.ts +1 -1
- package/src/data-tool.ts +19 -5
- package/src/design-tool.ts +74 -60
- package/src/edit-tool.ts +119 -0
- package/src/editor.ts +297 -0
- package/src/engine.ts +8 -1
- package/src/export-tool.ts +87 -81
- package/src/index.ts +4 -0
- package/src/model-file.ts +49 -0
- package/src/presentation.ts +125 -0
- package/src/report-diff-tool.ts +7 -1
- package/src/report-view.ts +534 -451
- package/src/routing.ts +96 -0
- package/src/scan.ts +564 -0
- package/src/structure-tool.ts +33 -1
- package/src/structure.ts +37 -3
- package/src/tool.ts +19 -4
- package/src/uml-tool.ts +240 -230
|
@@ -1,137 +1,137 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: model-everything-report-reading
|
|
3
|
-
description: "Use when reading a report this plugin returned: what does the verdict mean, why did it come out this way, which field do I act on, and what does the report not prove. It gives the reading order — did it run, what did it decide, what next — where each family keeps its findings, and the two readings that are easy to get backwards. It reads reports; it does not produce or check models. Producing one is model-everything."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Model Everything — Reading a Report
|
|
7
|
-
|
|
8
|
-
Every tool in this plugin returns a report, and a report is a claim about a model. This skill is the
|
|
9
|
-
reading order: which field answers which question, where the findings are in each family, and what
|
|
10
|
-
the report does not prove.
|
|
11
|
-
|
|
12
|
-
Load the `model-everything` skill to *produce* a model or to check a claim. Load this one when a
|
|
13
|
-
report is already in hand and the question is what it says.
|
|
14
|
-
|
|
15
|
-
## The Reading Order
|
|
16
|
-
|
|
17
|
-
Three questions, in this order. Each one can make the next unnecessary.
|
|
18
|
-
|
|
19
|
-
### Did it run?
|
|
20
|
-
|
|
21
|
-
`ran` separates a tool that refused from one that ran, but it answers that question for one kind of
|
|
22
|
-
refusal only. A call refused at the boundary — an argument in the wrong shape, a format that does not
|
|
23
|
-
exist, a notation that is not one — comes back with `ran: false`, an `errorCode`, and a
|
|
24
|
-
`verdictReason` beginning "the tool did not run". Fix the call; there is no verdict to route on.
|
|
25
|
-
|
|
26
|
-
An input the engine's own schema rejects is a different shape and looks like a review: `ran: true`,
|
|
27
|
-
`ok: false`, `verdict: fail`, no `errorCode`, one finding under a check whose id is `MODEL`,
|
|
28
|
-
`DATA_MODEL` or `DESIGN`, and `summary.checksRun: 0`. Read it as "the input is the problem, not the
|
|
29
|
-
design". A model that was actually reviewed examined something, so a non-zero `checksRun` is what
|
|
30
|
-
separates a defective model from a malformed one.
|
|
31
|
-
|
|
32
|
-
A refusal and a failing review need different responses, and `ran` alone does not tell them apart:
|
|
33
|
-
the test is `ran: false`, or `checksRun: 0` beside a check named after the validation.
|
|
34
|
-
|
|
35
|
-
### What did it decide?
|
|
36
|
-
|
|
37
|
-
`verdict` is the answer:
|
|
38
|
-
|
|
39
|
-
| `verdict` | Means |
|
|
40
|
-
|---|---|
|
|
41
|
-
| `pass` | The checks ran and found nothing to report |
|
|
42
|
-
| `pass_with_findings` | Warnings only; nothing decided against the model |
|
|
43
|
-
| `fail` | At least one error finding |
|
|
44
|
-
|
|
45
|
-
Read `verdict`, never `ok`. `ok` carries a different historical meaning in each family — in most it
|
|
46
|
-
is `true` for a failing review, and a composition sets it to `false` when any error-severity finding
|
|
47
|
-
exists — so it cannot be read as a verdict, and reading it as one is how a reader concludes the
|
|
48
|
-
opposite of what the report says. A `verdict: "fail"` is a successful run that found something;
|
|
49
|
-
that is the normal way this plugin tells you about a defect.
|
|
50
|
-
|
|
51
|
-
`verdictReason` is the one-line why and names the first error code. When the verdict is not what you
|
|
52
|
-
expected, start there.
|
|
53
|
-
|
|
54
|
-
### What should I do?
|
|
55
|
-
|
|
56
|
-
`nextSteps` is never empty and is derived from the findings rather than written beside them. It
|
|
57
|
-
names the route to whatever covers the ground the report does not: another check, a
|
|
58
|
-
source-side scan, or an external checker.
|
|
59
|
-
|
|
60
|
-
## Where the Findings Are
|
|
61
|
-
|
|
62
|
-
This is the part that varies, and it is worth knowing before you go looking:
|
|
63
|
-
|
|
64
|
-
| Where | Families |
|
|
65
|
-
|---|---|
|
|
66
|
-
| Inside each check, as `checks[].findings` | `model_verify`, `model_compose_verify`, `model_datamodel_verify`, `model_design_review` |
|
|
67
|
-
| At the top level, as `findings` | `uml_structure_verify`, the `uml` review path, `model_interleaving_scan` |
|
|
68
|
-
| Nowhere — compare `added` / `changed` / `removed` | `report_diff` |
|
|
69
|
-
|
|
70
|
-
A check-carried finding is attributed to a check, and the check carries a status of its own: `pass`,
|
|
71
|
-
`fail`, or `skip`. A top-level finding has no check to attribute it to, which is why those families
|
|
72
|
-
report a `summary` instead.
|
|
73
|
-
|
|
74
|
-
`report_diff` has no findings because its subject is the difference between two other reports.
|
|
75
|
-
`verdict` describes the delta and `currentVerdict` describes the current run on its own terms. They
|
|
76
|
-
differ exactly when the run is not clean but the delta is empty: comparing a failing report against
|
|
77
|
-
itself gives `verdict: "pass", currentVerdict: "fail"`, and both are true — nothing changed, and the
|
|
78
|
-
run fails.
|
|
79
|
-
|
|
80
|
-
## Severity Before Code
|
|
81
|
-
|
|
82
|
-
Within a finding, the severity decides whether it changed the verdict:
|
|
83
|
-
|
|
84
|
-
- **error** — what makes the verdict `fail`;
|
|
85
|
-
- **warning** — reported, does not fail the delta;
|
|
86
|
-
- **info** — context, for example that one element makes an inseparable group of findings;
|
|
87
|
-
- **undecided** — the search stopped before deciding. Not a pass. `summary.truncated` says the same
|
|
88
|
-
for the report as a whole.
|
|
89
|
-
|
|
90
|
-
The code prefix names the check that owns the finding (`S1`, `A4`, `DS5`, `DA2`, `DES12`, `UML023`),
|
|
91
|
-
so a code tells you where to look before you read its message.
|
|
92
|
-
|
|
93
|
-
### A code is for you, not for the person you are answering
|
|
94
|
-
|
|
95
|
-
The codes exist so you can route the finding to the right reference and re-check it. A user who never
|
|
96
|
-
read the report has no idea what `A4_NO_RELEASE_EVENT` means, and a reply that recites codes makes the
|
|
97
|
-
work look opaque while telling them nothing they can act on.
|
|
98
|
-
|
|
99
|
-
**Say what the finding says, in words.** The finding's own `message` is already a sentence written for a
|
|
100
|
-
reader who does not know the codes - use it. Name the code afterwards only if it helps the user find the
|
|
101
|
-
same line in the report, and then give it a meaning: not "S7 failed" but "the invariant is violated - the
|
|
102
|
-
model reaches C after two events (`S7_INVARIANT_VIOLATION`)".
|
|
103
|
-
|
|
104
|
-
The same goes for a check id: `Event Completeness` is the name, `S5` is the label. Lead with the name.
|
|
105
|
-
|
|
106
|
-
A model whose reachable state space is infinite is reported as `S6_UNBOUNDED_VARIABLE`, an error. It
|
|
107
|
-
is a property of the model, not a defect of the search: no search bound would have decided the
|
|
108
|
-
question. When you relay this one, relay the reason: *any* search bound would leave it undecided.
|
|
109
|
-
|
|
110
|
-
## What a Report Does Not Tell You
|
|
111
|
-
|
|
112
|
-
- **It is about the model, not the code.** A clean verdict is evidence about the drawing you
|
|
113
|
-
supplied. Reconciling it with the source is a separate step, and the difference between the two is
|
|
114
|
-
where the finding usually is.
|
|
115
|
-
- **A truncated search decided nothing.** When `truncated` is true, the checks that stopped early
|
|
116
|
-
report themselves as undecided rather than as passes.
|
|
117
|
-
- **A skipped check examined nothing.** `skip` and `pass` are different answers: a check with no
|
|
118
|
-
vocabulary to work with did not look, and saying so is the point.
|
|
119
|
-
|
|
120
|
-
## The Design Review's Three Lists
|
|
121
|
-
|
|
122
|
-
One family splits its findings, and only the first list decides anything:
|
|
123
|
-
|
|
124
|
-
- `violations` — the check level that decides the verdict;
|
|
125
|
-
- `signals` — worth a look, fails nothing;
|
|
126
|
-
- `facts` — no findings at all: one measurement object with the graph's numbers (`density`, `ranks`,
|
|
127
|
-
`articulationPoints`, `feedbackArcs`, `largestCycle`) and `checksSkipped`, which is where a reader
|
|
128
|
-
learns which checks never ran for want of a declaration.
|
|
129
|
-
|
|
130
|
-
No code appears in both lists, so a reader who reads only `violations` sees every finding that
|
|
131
|
-
decided the verdict and none that did not.
|
|
132
|
-
|
|
133
|
-
## Reference
|
|
134
|
-
|
|
135
|
-
[references/reading-a-report.md](references/reading-a-report.md) is the same method with the
|
|
136
|
-
worked detail: the shared skeleton field by field, what each family adds, and where the map that
|
|
137
|
-
structures it lives.
|
|
1
|
+
---
|
|
2
|
+
name: model-everything-report-reading
|
|
3
|
+
description: "Use when reading a report this plugin returned: what does the verdict mean, why did it come out this way, which field do I act on, and what does the report not prove. It gives the reading order — did it run, what did it decide, what next — where each family keeps its findings, and the two readings that are easy to get backwards. It reads reports; it does not produce or check models. Producing one is model-everything."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Model Everything — Reading a Report
|
|
7
|
+
|
|
8
|
+
Every tool in this plugin returns a report, and a report is a claim about a model. This skill is the
|
|
9
|
+
reading order: which field answers which question, where the findings are in each family, and what
|
|
10
|
+
the report does not prove.
|
|
11
|
+
|
|
12
|
+
Load the `model-everything` skill to *produce* a model or to check a claim. Load this one when a
|
|
13
|
+
report is already in hand and the question is what it says.
|
|
14
|
+
|
|
15
|
+
## The Reading Order
|
|
16
|
+
|
|
17
|
+
Three questions, in this order. Each one can make the next unnecessary.
|
|
18
|
+
|
|
19
|
+
### Did it run?
|
|
20
|
+
|
|
21
|
+
`ran` separates a tool that refused from one that ran, but it answers that question for one kind of
|
|
22
|
+
refusal only. A call refused at the boundary — an argument in the wrong shape, a format that does not
|
|
23
|
+
exist, a notation that is not one — comes back with `ran: false`, an `errorCode`, and a
|
|
24
|
+
`verdictReason` beginning "the tool did not run". Fix the call; there is no verdict to route on.
|
|
25
|
+
|
|
26
|
+
An input the engine's own schema rejects is a different shape and looks like a review: `ran: true`,
|
|
27
|
+
`ok: false`, `verdict: fail`, no `errorCode`, one finding under a check whose id is `MODEL`,
|
|
28
|
+
`DATA_MODEL` or `DESIGN`, and `summary.checksRun: 0`. Read it as "the input is the problem, not the
|
|
29
|
+
design". A model that was actually reviewed examined something, so a non-zero `checksRun` is what
|
|
30
|
+
separates a defective model from a malformed one.
|
|
31
|
+
|
|
32
|
+
A refusal and a failing review need different responses, and `ran` alone does not tell them apart:
|
|
33
|
+
the test is `ran: false`, or `checksRun: 0` beside a check named after the validation.
|
|
34
|
+
|
|
35
|
+
### What did it decide?
|
|
36
|
+
|
|
37
|
+
`verdict` is the answer:
|
|
38
|
+
|
|
39
|
+
| `verdict` | Means |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `pass` | The checks ran and found nothing to report |
|
|
42
|
+
| `pass_with_findings` | Warnings only; nothing decided against the model |
|
|
43
|
+
| `fail` | At least one error finding |
|
|
44
|
+
|
|
45
|
+
Read `verdict`, never `ok`. `ok` carries a different historical meaning in each family — in most it
|
|
46
|
+
is `true` for a failing review, and a composition sets it to `false` when any error-severity finding
|
|
47
|
+
exists — so it cannot be read as a verdict, and reading it as one is how a reader concludes the
|
|
48
|
+
opposite of what the report says. A `verdict: "fail"` is a successful run that found something;
|
|
49
|
+
that is the normal way this plugin tells you about a defect.
|
|
50
|
+
|
|
51
|
+
`verdictReason` is the one-line why and names the first error code. When the verdict is not what you
|
|
52
|
+
expected, start there.
|
|
53
|
+
|
|
54
|
+
### What should I do?
|
|
55
|
+
|
|
56
|
+
`nextSteps` is never empty and is derived from the findings rather than written beside them. It
|
|
57
|
+
names the route to whatever covers the ground the report does not: another check, a
|
|
58
|
+
source-side scan, or an external checker.
|
|
59
|
+
|
|
60
|
+
## Where the Findings Are
|
|
61
|
+
|
|
62
|
+
This is the part that varies, and it is worth knowing before you go looking:
|
|
63
|
+
|
|
64
|
+
| Where | Families |
|
|
65
|
+
|---|---|
|
|
66
|
+
| Inside each check, as `checks[].findings` | `model_verify`, `model_compose_verify`, `model_datamodel_verify`, `model_design_review` |
|
|
67
|
+
| At the top level, as `findings` | `uml_structure_verify`, the `uml` review path, `model_interleaving_scan` |
|
|
68
|
+
| Nowhere — compare `added` / `changed` / `removed` | `report_diff` |
|
|
69
|
+
|
|
70
|
+
A check-carried finding is attributed to a check, and the check carries a status of its own: `pass`,
|
|
71
|
+
`fail`, or `skip`. A top-level finding has no check to attribute it to, which is why those families
|
|
72
|
+
report a `summary` instead.
|
|
73
|
+
|
|
74
|
+
`report_diff` has no findings because its subject is the difference between two other reports.
|
|
75
|
+
`verdict` describes the delta and `currentVerdict` describes the current run on its own terms. They
|
|
76
|
+
differ exactly when the run is not clean but the delta is empty: comparing a failing report against
|
|
77
|
+
itself gives `verdict: "pass", currentVerdict: "fail"`, and both are true — nothing changed, and the
|
|
78
|
+
run fails.
|
|
79
|
+
|
|
80
|
+
## Severity Before Code
|
|
81
|
+
|
|
82
|
+
Within a finding, the severity decides whether it changed the verdict:
|
|
83
|
+
|
|
84
|
+
- **error** — what makes the verdict `fail`;
|
|
85
|
+
- **warning** — reported, does not fail the delta;
|
|
86
|
+
- **info** — context, for example that one element makes an inseparable group of findings;
|
|
87
|
+
- **undecided** — the search stopped before deciding. Not a pass. `summary.truncated` says the same
|
|
88
|
+
for the report as a whole.
|
|
89
|
+
|
|
90
|
+
The code prefix names the check that owns the finding (`S1`, `A4`, `DS5`, `DA2`, `DES12`, `UML023`),
|
|
91
|
+
so a code tells you where to look before you read its message.
|
|
92
|
+
|
|
93
|
+
### A code is for you, not for the person you are answering
|
|
94
|
+
|
|
95
|
+
The codes exist so you can route the finding to the right reference and re-check it. A user who never
|
|
96
|
+
read the report has no idea what `A4_NO_RELEASE_EVENT` means, and a reply that recites codes makes the
|
|
97
|
+
work look opaque while telling them nothing they can act on.
|
|
98
|
+
|
|
99
|
+
**Say what the finding says, in words.** The finding's own `message` is already a sentence written for a
|
|
100
|
+
reader who does not know the codes - use it. Name the code afterwards only if it helps the user find the
|
|
101
|
+
same line in the report, and then give it a meaning: not "S7 failed" but "the invariant is violated - the
|
|
102
|
+
model reaches C after two events (`S7_INVARIANT_VIOLATION`)".
|
|
103
|
+
|
|
104
|
+
The same goes for a check id: `Event Completeness` is the name, `S5` is the label. Lead with the name.
|
|
105
|
+
|
|
106
|
+
A model whose reachable state space is infinite is reported as `S6_UNBOUNDED_VARIABLE`, an error. It
|
|
107
|
+
is a property of the model, not a defect of the search: no search bound would have decided the
|
|
108
|
+
question. When you relay this one, relay the reason: *any* search bound would leave it undecided.
|
|
109
|
+
|
|
110
|
+
## What a Report Does Not Tell You
|
|
111
|
+
|
|
112
|
+
- **It is about the model, not the code.** A clean verdict is evidence about the drawing you
|
|
113
|
+
supplied. Reconciling it with the source is a separate step, and the difference between the two is
|
|
114
|
+
where the finding usually is.
|
|
115
|
+
- **A truncated search decided nothing.** When `truncated` is true, the checks that stopped early
|
|
116
|
+
report themselves as undecided rather than as passes.
|
|
117
|
+
- **A skipped check examined nothing.** `skip` and `pass` are different answers: a check with no
|
|
118
|
+
vocabulary to work with did not look, and saying so is the point.
|
|
119
|
+
|
|
120
|
+
## The Design Review's Three Lists
|
|
121
|
+
|
|
122
|
+
One family splits its findings, and only the first list decides anything:
|
|
123
|
+
|
|
124
|
+
- `violations` — the check level that decides the verdict;
|
|
125
|
+
- `signals` — worth a look, fails nothing;
|
|
126
|
+
- `facts` — no findings at all: one measurement object with the graph's numbers (`density`, `ranks`,
|
|
127
|
+
`articulationPoints`, `feedbackArcs`, `largestCycle`) and `checksSkipped`, which is where a reader
|
|
128
|
+
learns which checks never ran for want of a declaration.
|
|
129
|
+
|
|
130
|
+
No code appears in both lists, so a reader who reads only `violations` sees every finding that
|
|
131
|
+
decided the verdict and none that did not.
|
|
132
|
+
|
|
133
|
+
## Reference
|
|
134
|
+
|
|
135
|
+
[references/reading-a-report.md](references/reading-a-report.md) is the same method with the
|
|
136
|
+
worked detail: the shared skeleton field by field, what each family adds, and where the map that
|
|
137
|
+
structures it lives.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `model_automaton_verify`: what language does this machine accept, and is it the one it claims.
|
|
3
|
+
*
|
|
4
|
+
* The description is written for the decision. A conformance claim - "the implementation allows every run
|
|
5
|
+
* the specification allows" - is a language inclusion, and the two machines can be small while the
|
|
6
|
+
* question is still beyond a reading: the witness is a word nobody thought to try.
|
|
7
|
+
*/
|
|
8
|
+
import { defineTool } from '@deepseek-ai/dsh-tools'
|
|
9
|
+
|
|
10
|
+
import { verifyAutomaton, type AutomatonRelation } from './automaton.js'
|
|
11
|
+
import type { JsonValue } from './json-value.js'
|
|
12
|
+
import { optionRefusal } from './option-shape.js'
|
|
13
|
+
import { renderReportText } from './report-view.js'
|
|
14
|
+
import { reportCard, reportResultView } from './presentation.js'
|
|
15
|
+
|
|
16
|
+
export const MODEL_AUTOMATON_TOOL_NAME = 'model_automaton_verify'
|
|
17
|
+
|
|
18
|
+
export const modelAutomatonTool = defineTool({
|
|
19
|
+
name: MODEL_AUTOMATON_TOOL_NAME,
|
|
20
|
+
description:
|
|
21
|
+
'Decide a finite-word automaton: what it accepts, whether it is empty, whether a state is a trap, and whether its language equals, contains or is contained in another automaton. Use it for a conformance claim - the protocol the code implements against the one the specification draws - where the answer is a word that one machine accepts and the other rejects, not an opinion. ' +
|
|
22
|
+
'Give `other` to compare two automata; `relation` picks equivalent (default), subset (the first is contained in the second) or superset. A failed relation returns the shortest witness word. ' +
|
|
23
|
+
'Determinism, reachability and trap states are reported whether or not `other` is given. ' +
|
|
24
|
+
'It decides finite words over an explicit alphabet. Liveness, fairness, timing and infinite words are out of scope: a Büchi or timed model is a different family, and this tool does not build one. For reachability or deadlock in a single state machine use `model_verify`; for machines that must handshake use `model_compose_verify`.',
|
|
25
|
+
parameters: {
|
|
26
|
+
automaton: {
|
|
27
|
+
type: 'json',
|
|
28
|
+
required: true,
|
|
29
|
+
description: 'The automaton: {states: [ids], alphabet: [symbols], transitions: [{from, symbol, to}], init, accepting: [ids]}. An NFA is accepted and determinised; nondeterminism is reported.',
|
|
30
|
+
},
|
|
31
|
+
other: {
|
|
32
|
+
type: 'json',
|
|
33
|
+
description: 'The automaton to compare against, in the same shape. Omit to check this one on its own.',
|
|
34
|
+
},
|
|
35
|
+
relation: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
enum: ['equivalent', 'subset', 'superset'],
|
|
38
|
+
description: 'Which language relation `other` must stand in. Default equivalent. subset: the first is contained in the second; superset: the second is contained in the first.',
|
|
39
|
+
},
|
|
40
|
+
reportView: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
enum: ['digest', 'full'],
|
|
43
|
+
description: 'digest (default) prints the readable body; full prints the structured result.',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
output: {
|
|
47
|
+
schema: {
|
|
48
|
+
type: 'json',
|
|
49
|
+
description: 'the automaton report: verdict, findings, the witness word when a relation fails, and hashes of the inputs.',
|
|
50
|
+
},
|
|
51
|
+
render(args, value) {
|
|
52
|
+
return [{ type: 'text' as const, text: renderReportText(value, { full: args.reportView === 'full' }) }]
|
|
53
|
+
},
|
|
54
|
+
// The card a UI shows, separated from the text the model reads: a verdict and the first thing wrong,
|
|
55
|
+
// never the whole report.
|
|
56
|
+
presentationMeta(_args, value) {
|
|
57
|
+
return reportCard(value, MODEL_AUTOMATON_TOOL_NAME) as unknown as JsonValue
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
presentResult: reportResultView(MODEL_AUTOMATON_TOOL_NAME),
|
|
61
|
+
timeoutMs: 10_000,
|
|
62
|
+
isConcurrencySafe: () => true,
|
|
63
|
+
async execute(args) {
|
|
64
|
+
try {
|
|
65
|
+
return verifyAutomaton(args.automaton, {
|
|
66
|
+
...(args.other === undefined ? {} : { other: args.other }),
|
|
67
|
+
...(args.relation === undefined ? {} : { relation: args.relation as AutomatonRelation }),
|
|
68
|
+
}) as unknown as JsonValue
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return optionRefusal(error, 'AUTOMATON_OPTION_INVALID') as unknown as JsonValue
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
})
|