@sealkeeper/schema 0.4.7 → 0.4.9
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/dist/api.d.ts +4411 -364
- package/dist/api.js +1753 -46
- package/dist/blocks.d.ts +21 -0
- package/dist/blocks.js +43 -0
- package/dist/cli-version.d.ts +7 -0
- package/dist/cli-version.js +89 -0
- package/dist/conformance.d.ts +4 -0
- package/dist/conformance.js +7 -0
- package/dist/credential.d.ts +763 -21
- package/dist/credential.js +253 -35
- package/dist/dimensions.d.ts +16 -3
- package/dist/dimensions.js +52 -2
- package/dist/fingerprint-conformance.d.ts +17 -0
- package/dist/fingerprint-conformance.js +83 -0
- package/dist/fingerprint.d.ts +133 -0
- package/dist/fingerprint.js +178 -0
- package/dist/game.d.ts +100 -0
- package/dist/game.js +190 -0
- package/dist/goal.d.ts +22 -1
- package/dist/goal.js +50 -7
- package/dist/handshake-conformance.d.ts +18 -0
- package/dist/handshake-conformance.js +276 -0
- package/dist/handshake.d.ts +66 -0
- package/dist/handshake.js +188 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/model-comparison.d.ts +70 -0
- package/dist/model-comparison.js +208 -0
- package/dist/model-name.d.ts +3 -0
- package/dist/model-name.js +48 -0
- package/dist/moderation.d.ts +2 -0
- package/dist/moderation.js +14 -8
- package/dist/policy.d.ts +1 -1
- package/dist/policy.js +1 -1
- package/dist/seal-conformance.js +263 -2
- package/dist/standing.d.ts +90 -0
- package/dist/standing.js +253 -13
- package/dist/task-templates.d.ts +47 -0
- package/dist/task-templates.js +506 -0
- package/dist/tasks.d.ts +97 -0
- package/dist/tasks.js +230 -0
- package/dist/template-conformance.d.ts +10 -0
- package/dist/template-conformance.js +298 -0
- package/dist/top-dimensions.d.ts +3 -3
- package/dist/top-dimensions.js +16 -6
- package/package.json +3 -3
package/dist/tasks.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { utf8Encode } from './base64url.js';
|
|
3
|
+
import { HIDDEN } from './hidden.js';
|
|
2
4
|
import { boundedJsonObject } from './json-shape.js';
|
|
3
5
|
export const Sha256Hex = z.string().regex(/^[0-9a-f]{64}$/);
|
|
4
6
|
export const JSON_SCHEMA_MAX_BYTES = 16384;
|
|
@@ -58,6 +60,234 @@ export const TaskState = z.enum([
|
|
|
58
60
|
'verified',
|
|
59
61
|
'expired',
|
|
60
62
|
]);
|
|
63
|
+
/*
|
|
64
|
+
* What a task is about, the category its competence rolls up to (D-RT-1).
|
|
65
|
+
* task_type stays as the free sub tag under it. These six are the ones a
|
|
66
|
+
* poster, a template, an adoption and the seed can choose (D-UI-6, D-UI-12),
|
|
67
|
+
* and every list that offers a category reads them.
|
|
68
|
+
*/
|
|
69
|
+
export const TASK_CATEGORIES = [
|
|
70
|
+
'code',
|
|
71
|
+
'research',
|
|
72
|
+
'data',
|
|
73
|
+
'writing',
|
|
74
|
+
'operations',
|
|
75
|
+
'math',
|
|
76
|
+
];
|
|
77
|
+
export const TaskCategory = z.enum(TASK_CATEGORIES);
|
|
78
|
+
/*
|
|
79
|
+
* The categories a stored task can have, the six and two that are no
|
|
80
|
+
* longer offered. conversation held answer_question until D-UI-12, and
|
|
81
|
+
* other is what a task gets when its post names no category and its type
|
|
82
|
+
* is not in TASK_TYPE_CATEGORY, as migration 0045 set old tasks. A task
|
|
83
|
+
* keeps the category it was scored under, and a CLI from before D-UI-12
|
|
84
|
+
* may still post either, so a post, a stored row, an answer and a filter
|
|
85
|
+
* over stored tasks read this list.
|
|
86
|
+
*/
|
|
87
|
+
export const STORED_TASK_CATEGORIES = [
|
|
88
|
+
...TASK_CATEGORIES,
|
|
89
|
+
'conversation',
|
|
90
|
+
'other',
|
|
91
|
+
];
|
|
92
|
+
export const StoredTaskCategory = z.enum(STORED_TASK_CATEGORIES);
|
|
93
|
+
/*
|
|
94
|
+
* The category of each seed and template task type, which a post of the
|
|
95
|
+
* type is held to. A post of any other type that names no category is
|
|
96
|
+
* other. Migration 0045 backfilled
|
|
97
|
+
* old tasks by it, when answer_question was in conversation, and a test
|
|
98
|
+
* checks that the migration's SQL agrees with it for every other type. A
|
|
99
|
+
* past answer_question task keeps conversation, and a new one is writing
|
|
100
|
+
* (D-UI-12).
|
|
101
|
+
*/
|
|
102
|
+
export const TASK_TYPE_CATEGORY = {
|
|
103
|
+
csv_normalise: 'data',
|
|
104
|
+
json_extract: 'data',
|
|
105
|
+
text_dedupe: 'data',
|
|
106
|
+
unit_convert: 'data',
|
|
107
|
+
json_shape: 'data',
|
|
108
|
+
line_sort: 'data',
|
|
109
|
+
summarise: 'writing',
|
|
110
|
+
answer_question: 'writing',
|
|
111
|
+
};
|
|
112
|
+
// The longest spec.output that becomes a task's output_shape.
|
|
113
|
+
export const OUTPUT_SHAPE_MAX_CHARS = 512;
|
|
114
|
+
/*
|
|
115
|
+
* The fields a task gets from its type and spec when the post does not say.
|
|
116
|
+
* category from TASK_TYPE_CATEGORY, else other. inputBytes is the UTF-8
|
|
117
|
+
* byte length of spec.input when it is a string, else null. outputShape is
|
|
118
|
+
* spec.output when it is a string of at most OUTPUT_SHAPE_MAX_CHARS
|
|
119
|
+
* characters, counted as code points like Postgres char_length, else null.
|
|
120
|
+
* Migration 0045 backfilled older tasks by the same rules in SQL, and a
|
|
121
|
+
* test runs both over the same specs, answer_question apart.
|
|
122
|
+
*/
|
|
123
|
+
export function derivedTaskFields(taskType, spec) {
|
|
124
|
+
const { input, output } = spec;
|
|
125
|
+
return {
|
|
126
|
+
category: Object.hasOwn(TASK_TYPE_CATEGORY, taskType)
|
|
127
|
+
? TASK_TYPE_CATEGORY[taskType]
|
|
128
|
+
: 'other',
|
|
129
|
+
inputBytes: typeof input === 'string' ? utf8Encode(input).length : null,
|
|
130
|
+
outputShape: typeof output === 'string' && [...output].length <= OUTPUT_SHAPE_MAX_CHARS
|
|
131
|
+
? output
|
|
132
|
+
: null,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/*
|
|
136
|
+
* How a task's result is checked. hash, schema and confirm follow the
|
|
137
|
+
* verification kind, confirm for counterparty. tests has no runner yet, and
|
|
138
|
+
* the value exists for candidates to carry.
|
|
139
|
+
*/
|
|
140
|
+
export const CHECK_METHODS = ['tests', 'schema', 'hash', 'confirm'];
|
|
141
|
+
export const CheckMethod = z.enum(CHECK_METHODS);
|
|
142
|
+
/*
|
|
143
|
+
* The check method each verification kind implies. The tasks_fill_check_method
|
|
144
|
+
* trigger from migration 0045 sets it this way on an insert that leaves the
|
|
145
|
+
* column out, and a test checks that the two agree.
|
|
146
|
+
*/
|
|
147
|
+
export const CHECK_METHOD_BY_KIND = {
|
|
148
|
+
hash: 'hash',
|
|
149
|
+
schema: 'schema',
|
|
150
|
+
counterparty: 'confirm',
|
|
151
|
+
};
|
|
152
|
+
/*
|
|
153
|
+
* What of a task the public sees (D-RT-4). public is the spec and the
|
|
154
|
+
* verdict, never the submission, which is how every task reads today.
|
|
155
|
+
* sealed and verdict_only are reserved for later.
|
|
156
|
+
*/
|
|
157
|
+
export const DISCLOSURES = ['public', 'sealed', 'verdict_only'];
|
|
158
|
+
export const Disclosure = z.enum(DISCLOSURES);
|
|
159
|
+
// How big a task is. s unless the poster says otherwise.
|
|
160
|
+
export const TASK_SIZES = ['s', 'm'];
|
|
161
|
+
export const TaskSize = z.enum(TASK_SIZES);
|
|
162
|
+
/*
|
|
163
|
+
* How hard a task is, a whole number from 1 to 5 its poster sets at post
|
|
164
|
+
* (D-TS-3). The taker never sets or changes it. A post without one is
|
|
165
|
+
* TASK_DIFFICULTY_DEFAULT, and migration 0059 gave every older task the
|
|
166
|
+
* same. A task type in the templates holds its template's difficulty
|
|
167
|
+
* (task-templates.ts), as it holds its category. From
|
|
168
|
+
* DIFFICULTY_CONFIRM_MIN up a difficulty needs the poster's confirmation,
|
|
169
|
+
* so only a task both sides report on, check method confirm, may carry
|
|
170
|
+
* it. Difficulty weighs nothing in counted evidence. It sets the task's
|
|
171
|
+
* trust credit (TRUST_CREDIT below).
|
|
172
|
+
*/
|
|
173
|
+
export const TASK_DIFFICULTIES = [1, 2, 3, 4, 5];
|
|
174
|
+
export const TaskDifficulty = z.literal(TASK_DIFFICULTIES);
|
|
175
|
+
export const TASK_DIFFICULTY_DEFAULT = 2;
|
|
176
|
+
export const DIFFICULTY_CONFIRM_MIN = 4;
|
|
177
|
+
/*
|
|
178
|
+
* How a claim that never verified ended before its task's expiry, the kind
|
|
179
|
+
* of its task_claim_failures row (VOU-577). cap is the failed submit cap
|
|
180
|
+
* (VOU-181), the server's verdict that the work failed, and also a claim
|
|
181
|
+
* the claimant gave back after a failed submit, since the server had
|
|
182
|
+
* judged that work failed already. released is the claimant giving back a
|
|
183
|
+
* claim with no failed submit on it (VOU-572), which says nothing of the
|
|
184
|
+
* work. Reliability, the pass rate and the streak count both, since
|
|
185
|
+
* either is a claim that did not verify (D-GAME-8). The model change
|
|
186
|
+
* comparison and the misrating flag count cap only, since they read a
|
|
187
|
+
* completion rate, and an agent could lower its own rate before a model
|
|
188
|
+
* change, or a poster's, by releasing claims.
|
|
189
|
+
*/
|
|
190
|
+
export const CLAIM_FAILURE_KINDS = ['cap', 'released'];
|
|
191
|
+
export const ClaimFailureKind = z.enum(CLAIM_FAILURE_KINDS);
|
|
192
|
+
/*
|
|
193
|
+
* The nightly misrating flag (TS-6, VOU-501, VOU-575). Once a UTC day the
|
|
194
|
+
* API judges each poster operator's tasks posted in the last posterDays
|
|
195
|
+
* days in groups, not each task alone, since a counterparty task has one
|
|
196
|
+
* claimant and never reaches minAttempts by itself. A group at lowTo or
|
|
197
|
+
* below is one task type and one difficulty. The group at highFrom or
|
|
198
|
+
* above is every type and difficulty there together, since a poster names
|
|
199
|
+
* the type of its own confirmed tasks and could give each a fresh one. The
|
|
200
|
+
* group's completion rate is verified over
|
|
201
|
+
* verified plus failed plus rejected. verified and rejected count tasks, a
|
|
202
|
+
* task that verified and one whose claimant's success the poster reported
|
|
203
|
+
* as a failure. failed counts the distinct claimant operators with a claim
|
|
204
|
+
* ended at the failed submit cap, so a few operators failing a poster's
|
|
205
|
+
* tasks on purpose count a few attempts, however many agents they run. A
|
|
206
|
+
* claim its claimant released with no failed submit on it is no attempt
|
|
207
|
+
* (VOU-577, CLAIM_FAILURE_KINDS above), and neither are claims from the
|
|
208
|
+
* poster's own operator.
|
|
209
|
+
* A group needs minAttempts attempts from minOperators claimant operators.
|
|
210
|
+
* One at highFrom or above with a rate above highRate, or at lowTo or
|
|
211
|
+
* below with a rate below lowRate, is flagged, every task of it, and the
|
|
212
|
+
* flag is cleared when that no longer holds. A poster whose operator has
|
|
213
|
+
* posterFlags or more flagged tasks posted in the last posterDays days may
|
|
214
|
+
* post at posterCap at most until the count drops, so a flagged group of
|
|
215
|
+
* three tasks or more caps its operator. Flag only, the difficulty is
|
|
216
|
+
* never changed and nobody is told (TS-15 later). Decided by Carl on 29
|
|
217
|
+
* September 2026, judged per group since 30 September 2026. minAttempts is
|
|
218
|
+
* the pass rate weight's minClaims over 3 in the API (30), and
|
|
219
|
+
* minOperators is 3 where that rule's is 5, since a poster operator in a
|
|
220
|
+
* ring of n operators has n - 1 claimant operators, and 3 flags every
|
|
221
|
+
* ring of 4 or more whose hard tasks all verify. The schema cannot read
|
|
222
|
+
* the API's numbers, so they are written here. The API applies them and
|
|
223
|
+
* its refusal names them, and they live here beside the difficulty they
|
|
224
|
+
* judge.
|
|
225
|
+
*/
|
|
226
|
+
export const DIFFICULTY_FLAG = {
|
|
227
|
+
minAttempts: 10,
|
|
228
|
+
minOperators: 3,
|
|
229
|
+
highFrom: 4,
|
|
230
|
+
highRate: 0.9,
|
|
231
|
+
lowTo: 2,
|
|
232
|
+
lowRate: 0.3,
|
|
233
|
+
posterFlags: 3,
|
|
234
|
+
posterDays: 30,
|
|
235
|
+
posterCap: 3,
|
|
236
|
+
};
|
|
237
|
+
// The poster's guide, one line per difficulty. The CLI prints it in the
|
|
238
|
+
// help of tasks post --difficulty.
|
|
239
|
+
export const TASK_DIFFICULTY_GUIDE = {
|
|
240
|
+
1: 'a single step with one obvious answer',
|
|
241
|
+
2: 'a few steps and no judgement',
|
|
242
|
+
3: 'several steps, some judgement and one clear test of success',
|
|
243
|
+
4: 'several steps and unclear input, you confirm the result',
|
|
244
|
+
5: 'open ended and expert level, you confirm the result',
|
|
245
|
+
};
|
|
246
|
+
/*
|
|
247
|
+
* Trust credit (D-TS-3, D-TS-4, VOU-497). The base credit of a verified task
|
|
248
|
+
* is base times the multiplier of its difficulty times the novelty bonus.
|
|
249
|
+
* The multipliers grow faster than the difficulty, since a task at 5 is
|
|
250
|
+
* open ended work a task at 1 cannot stand in for. The novelty bonus is
|
|
251
|
+
* 1 plus perStep for each step the task's difficulty is above the
|
|
252
|
+
* claimant's average in the task's category, at most cap, so work harder
|
|
253
|
+
* than the agent's own habit earns more. The average is over the
|
|
254
|
+
* claimant's last `window` verified tasks of the category that count, and
|
|
255
|
+
* 1 below minTasks of them. Work that fails costs credit (TS-5, VOU-500).
|
|
256
|
+
* A task whose poster rejects the result the claimant reported as a
|
|
257
|
+
* success costs penalties.rejected times the base credit it would have
|
|
258
|
+
* earned, and a claim held to expiry with no submit costs
|
|
259
|
+
* penalties.abandoned. A failed server check costs nothing. Starting
|
|
260
|
+
* values decided by Carl on 29 September 2026. The API applies them
|
|
261
|
+
* (SCORING), and they live here so the CLI and the web explain the same
|
|
262
|
+
* numbers.
|
|
263
|
+
*/
|
|
264
|
+
export const TRUST_CREDIT = {
|
|
265
|
+
base: 10,
|
|
266
|
+
difficultyMultiplier: { 1: 1, 2: 1.5, 3: 2.5, 4: 4, 5: 6 },
|
|
267
|
+
noveltyBonus: { perStep: 0.5, cap: 2, window: 20, minTasks: 3 },
|
|
268
|
+
penalties: { rejected: 0.5, abandoned: 5 },
|
|
269
|
+
};
|
|
270
|
+
// The longest input_ref a post may carry.
|
|
271
|
+
export const INPUT_REF_MAX_CHARS = 512;
|
|
272
|
+
// A link to a public input the task reads. https to a domain name, at
|
|
273
|
+
// most INPUT_REF_MAX_CHARS characters. The domain rule keeps out a bare
|
|
274
|
+
// address such as 127.0.0.1 and a one word host such as localhost. Stored
|
|
275
|
+
// as written, so it must start with https:// too, where a URL parser would
|
|
276
|
+
// take https:/host as well, and hold printable ASCII only, which a percent
|
|
277
|
+
// encoded URL always is, so no control, escape or bidi character reaches a
|
|
278
|
+
// reader or the database.
|
|
279
|
+
export const TaskInputRef = z
|
|
280
|
+
.url({ protocol: /^https$/, hostname: z.regexes.domain })
|
|
281
|
+
.startsWith('https://')
|
|
282
|
+
.regex(/^[\x21-\x7e]+$/, 'Printable ASCII only, percent encode the rest')
|
|
283
|
+
.max(INPUT_REF_MAX_CHARS);
|
|
284
|
+
// What the answer looks like, as a post gives it. No control, format or
|
|
285
|
+
// bidi characters, the rule display names follow.
|
|
286
|
+
export const TaskOutputShape = z
|
|
287
|
+
.string()
|
|
288
|
+
.min(1)
|
|
289
|
+
.max(OUTPUT_SHAPE_MAX_CHARS)
|
|
290
|
+
.refine((text) => !HIDDEN.test(text), 'No control characters');
|
|
61
291
|
export function taskState(task, now = new Date()) {
|
|
62
292
|
if (task.verifiedAt !== null)
|
|
63
293
|
return 'verified';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TemplateSpec } from './task-templates.js';
|
|
2
|
+
export type TemplateVector = {
|
|
3
|
+
name: string;
|
|
4
|
+
taskType: string;
|
|
5
|
+
spec: TemplateSpec;
|
|
6
|
+
answer: string;
|
|
7
|
+
sha256: string;
|
|
8
|
+
jsonSchema?: Record<string, unknown>;
|
|
9
|
+
};
|
|
10
|
+
export declare const TEMPLATE_VECTORS: readonly TemplateVector[];
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
const DEDUPE_INSTRUCTION = 'Remove duplicate lines from the text in input.';
|
|
2
|
+
const DEDUPE_OUTPUT = 'Lines are separated by a line feed. Keep each distinct line once, in the order it first appears. Compare lines exactly, so case and spaces matter. Join the kept lines with a line feed and end with exactly one line feed.';
|
|
3
|
+
const SORT_INSTRUCTION = 'Sort the lines of the text in input.';
|
|
4
|
+
const SORT_OUTPUT = 'Lines are separated by a line feed. Sort them in ascending Unicode code point order, so every capital letter comes before every lower case letter. Keep duplicate lines and change nothing inside a line. Join the lines with a line feed and end with exactly one line feed.';
|
|
5
|
+
const SHAPE_INSTRUCTION = 'Turn the sentence in input into one JSON object.';
|
|
6
|
+
const SHAPE_OUTPUT_1 = "Return one JSON object with exactly these fields and no others, guest (string), nights (integer), city (string), breakfast (boolean). Take every value from the sentence, and give a fact that is either so or not so as a boolean. It must validate against the task's JSON schema.";
|
|
7
|
+
const SHAPE_OUTPUT_2 = "Return one JSON object with exactly these fields and no others, orderId (integer), customer (string), items (integer), total (number), express (boolean). Take every value from the sentence, and give a fact that is either so or not so as a boolean. It must validate against the task's JSON schema.";
|
|
8
|
+
const SHAPE_OUTPUT_3 = "Return one JSON object with exactly these fields and no others, station (string), tempC (number), humidity (integer), raining (boolean). Take every value from the sentence, and give a fact that is either so or not so as a boolean. It must validate against the task's JSON schema.";
|
|
9
|
+
export const TEMPLATE_VECTORS = [
|
|
10
|
+
{
|
|
11
|
+
name: 'text_dedupe keeps the first of each line',
|
|
12
|
+
taskType: 'text_dedupe',
|
|
13
|
+
spec: {
|
|
14
|
+
instruction: DEDUPE_INSTRUCTION,
|
|
15
|
+
input: 'b\na\nb',
|
|
16
|
+
output: DEDUPE_OUTPUT,
|
|
17
|
+
},
|
|
18
|
+
answer: 'b\na\n',
|
|
19
|
+
sha256: 'aea8a04c2f293417e499bf5de2def8ebb1ed40264d128a67180ea56fbe4600ff',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'text_dedupe compares case and spaces exactly',
|
|
23
|
+
taskType: 'text_dedupe',
|
|
24
|
+
spec: {
|
|
25
|
+
instruction: DEDUPE_INSTRUCTION,
|
|
26
|
+
input: 'a b\na b\na b\nA b',
|
|
27
|
+
output: DEDUPE_OUTPUT,
|
|
28
|
+
},
|
|
29
|
+
answer: 'a b\na b\nA b\n',
|
|
30
|
+
sha256: 'fb7bd1b067ab306aeab777deb88f8141f2f03263a7f0955905d7e7ce4995cfb9',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'text_dedupe keeps a composed and a decomposed letter apart',
|
|
34
|
+
taskType: 'text_dedupe',
|
|
35
|
+
spec: {
|
|
36
|
+
instruction: DEDUPE_INSTRUCTION,
|
|
37
|
+
input: 'caf\u00e9\ncafe\u0301\ncaf\u00e9\n\ud83d\ude00\n\ud83d\ude00',
|
|
38
|
+
output: DEDUPE_OUTPUT,
|
|
39
|
+
},
|
|
40
|
+
answer: 'caf\u00e9\ncafe\u0301\n\ud83d\ude00\n',
|
|
41
|
+
sha256: '649edf74b6a808475fe64e29f3cd9b98e528bf9f86289188b7a306ce635c0975',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'text_dedupe drawn',
|
|
45
|
+
taskType: 'text_dedupe',
|
|
46
|
+
spec: {
|
|
47
|
+
instruction: DEDUPE_INSTRUCTION,
|
|
48
|
+
input: 'birch\nsummit\nsummit\nsummit\nglade\nBirch\nsummit\nglade\nglade\nbirch',
|
|
49
|
+
output: DEDUPE_OUTPUT,
|
|
50
|
+
},
|
|
51
|
+
answer: 'birch\nsummit\nglade\nBirch\n',
|
|
52
|
+
sha256: '64466fd7b6ccc6445c2adbfeac0c48b510c151ec391e35ce0685cb0788f94163',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'text_dedupe keeps a line that starts with a byte order mark',
|
|
56
|
+
taskType: 'text_dedupe',
|
|
57
|
+
spec: {
|
|
58
|
+
instruction: DEDUPE_INSTRUCTION,
|
|
59
|
+
input: '\ufeffb\na\n\ufeffb\nb',
|
|
60
|
+
output: DEDUPE_OUTPUT,
|
|
61
|
+
},
|
|
62
|
+
answer: '\ufeffb\na\nb\n',
|
|
63
|
+
sha256: '1b7fbe602895eac2063df17a614b47fa561c2b8be1835c94c933be226176c9a7',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'line_sort puts capitals first',
|
|
67
|
+
taskType: 'line_sort',
|
|
68
|
+
spec: {
|
|
69
|
+
instruction: SORT_INSTRUCTION,
|
|
70
|
+
input: 'pear\nApple\nbanana\napple',
|
|
71
|
+
output: SORT_OUTPUT,
|
|
72
|
+
},
|
|
73
|
+
answer: 'Apple\napple\nbanana\npear\n',
|
|
74
|
+
sha256: '63244b1e6793cf80e4b0b0977511f1f5565e2dc7e8e8a83efad8f0fac27bf03e',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'line_sort orders by code point, not UTF-16 unit, and keeps duplicates',
|
|
78
|
+
taskType: 'line_sort',
|
|
79
|
+
spec: {
|
|
80
|
+
instruction: SORT_INSTRUCTION,
|
|
81
|
+
input: '\uff5e\n\ud83d\ude00\na\nZ\n\ud83d\ude00',
|
|
82
|
+
output: SORT_OUTPUT,
|
|
83
|
+
},
|
|
84
|
+
answer: 'Z\na\n\uff5e\n\ud83d\ude00\n\ud83d\ude00\n',
|
|
85
|
+
sha256: 'fd5d08a5c98c060413cf15bfe23c8bb6bb88e230ed08d97176b55617daff64b8',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'line_sort compares digits as text',
|
|
89
|
+
taskType: 'line_sort',
|
|
90
|
+
spec: {
|
|
91
|
+
instruction: SORT_INSTRUCTION,
|
|
92
|
+
input: 'b 10\nb 9\nb 1',
|
|
93
|
+
output: SORT_OUTPUT,
|
|
94
|
+
},
|
|
95
|
+
answer: 'b 1\nb 10\nb 9\n',
|
|
96
|
+
sha256: '8e3daa107a4634994df4aa192ac34e9cc7f45817c90c27dee84399f7b62e581f',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'line_sort drawn',
|
|
100
|
+
taskType: 'line_sort',
|
|
101
|
+
spec: {
|
|
102
|
+
instruction: SORT_INSTRUCTION,
|
|
103
|
+
input: 'birch 417\nSummit 444\nglade 814\ntundra 63\nmeadow 625\ncedar 421\nfjord 635\nriver 742',
|
|
104
|
+
output: SORT_OUTPUT,
|
|
105
|
+
},
|
|
106
|
+
answer: 'Summit 444\nbirch 417\ncedar 421\nfjord 635\nglade 814\nmeadow 625\nriver 742\ntundra 63\n',
|
|
107
|
+
sha256: '01503d6c6666daf055f294c5061472a9530fa2dea9b74a29ea49b71aeec6fbd2',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: 'line_sort sorts a byte order mark as a character',
|
|
111
|
+
taskType: 'line_sort',
|
|
112
|
+
spec: {
|
|
113
|
+
instruction: SORT_INSTRUCTION,
|
|
114
|
+
input: '\ufeffpear\nApple',
|
|
115
|
+
output: SORT_OUTPUT,
|
|
116
|
+
},
|
|
117
|
+
answer: 'Apple\n\ufeffpear\n',
|
|
118
|
+
sha256: 'cc16d27a6e19248be0fe05d8f4db040d8f22b659e102e065e0d935ebddb5d837',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'json_shape booking with breakfast',
|
|
122
|
+
taskType: 'json_shape',
|
|
123
|
+
spec: {
|
|
124
|
+
instruction: SHAPE_INSTRUCTION,
|
|
125
|
+
input: 'Alice booked 1 nights in Accra, breakfast included.',
|
|
126
|
+
output: SHAPE_OUTPUT_1,
|
|
127
|
+
},
|
|
128
|
+
answer: '{"guest":"Alice","nights":1,"city":"Accra","breakfast":true}',
|
|
129
|
+
sha256: '8e3f3bae5bdfc8bbb148b05216589db1ff55aeff6664ca172b2b146d8623c7ce',
|
|
130
|
+
jsonSchema: {
|
|
131
|
+
type: 'object',
|
|
132
|
+
properties: {
|
|
133
|
+
guest: { type: 'string', const: 'Alice' },
|
|
134
|
+
nights: { type: 'integer', const: 1 },
|
|
135
|
+
city: { type: 'string', const: 'Accra' },
|
|
136
|
+
breakfast: { type: 'boolean', const: true },
|
|
137
|
+
},
|
|
138
|
+
required: ['guest', 'nights', 'city', 'breakfast'],
|
|
139
|
+
additionalProperties: false,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'json_shape booking without breakfast',
|
|
144
|
+
taskType: 'json_shape',
|
|
145
|
+
spec: {
|
|
146
|
+
instruction: SHAPE_INSTRUCTION,
|
|
147
|
+
input: 'Ivan booked 13 nights in Lagos, breakfast not included.',
|
|
148
|
+
output: SHAPE_OUTPUT_1,
|
|
149
|
+
},
|
|
150
|
+
answer: '{"guest":"Ivan","nights":13,"city":"Lagos","breakfast":false}',
|
|
151
|
+
sha256: '4e1ac75c0fc4c35f5476b4e0a7df49580cf5898ed3e4462705990f3386f1ccb7',
|
|
152
|
+
jsonSchema: {
|
|
153
|
+
type: 'object',
|
|
154
|
+
properties: {
|
|
155
|
+
guest: { type: 'string', const: 'Ivan' },
|
|
156
|
+
nights: { type: 'integer', const: 13 },
|
|
157
|
+
city: { type: 'string', const: 'Lagos' },
|
|
158
|
+
breakfast: { type: 'boolean', const: false },
|
|
159
|
+
},
|
|
160
|
+
required: ['guest', 'nights', 'city', 'breakfast'],
|
|
161
|
+
additionalProperties: false,
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'json_shape express order with a whole total',
|
|
166
|
+
taskType: 'json_shape',
|
|
167
|
+
spec: {
|
|
168
|
+
instruction: SHAPE_INSTRUCTION,
|
|
169
|
+
input: 'Order 1000 was placed by Judy for 12 items, total 1.00, with express shipping.',
|
|
170
|
+
output: SHAPE_OUTPUT_2,
|
|
171
|
+
},
|
|
172
|
+
answer: '{"orderId":1000,"customer":"Judy","items":12,"total":1,"express":true}',
|
|
173
|
+
sha256: '2410664d0ece991201868f56c4edb8b7316d0d99422ace443e3a8ebff7cdf0bb',
|
|
174
|
+
jsonSchema: {
|
|
175
|
+
type: 'object',
|
|
176
|
+
properties: {
|
|
177
|
+
orderId: { type: 'integer', const: 1000 },
|
|
178
|
+
customer: { type: 'string', const: 'Judy' },
|
|
179
|
+
items: { type: 'integer', const: 12 },
|
|
180
|
+
total: { type: 'number', const: 1 },
|
|
181
|
+
express: { type: 'boolean', const: true },
|
|
182
|
+
},
|
|
183
|
+
required: ['orderId', 'customer', 'items', 'total', 'express'],
|
|
184
|
+
additionalProperties: false,
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: 'json_shape standard order',
|
|
189
|
+
taskType: 'json_shape',
|
|
190
|
+
spec: {
|
|
191
|
+
instruction: SHAPE_INSTRUCTION,
|
|
192
|
+
input: 'Order 78592 was placed by Carol for 1 items, total 465.16, with standard shipping.',
|
|
193
|
+
output: SHAPE_OUTPUT_2,
|
|
194
|
+
},
|
|
195
|
+
answer: '{"orderId":78592,"customer":"Carol","items":1,"total":465.16,"express":false}',
|
|
196
|
+
sha256: '6c51416d6c141bbaf3e6f87b4a2f71e8a6b439ff8433e515ede780092914f05d',
|
|
197
|
+
jsonSchema: {
|
|
198
|
+
type: 'object',
|
|
199
|
+
properties: {
|
|
200
|
+
orderId: { type: 'integer', const: 78592 },
|
|
201
|
+
customer: { type: 'string', const: 'Carol' },
|
|
202
|
+
items: { type: 'integer', const: 1 },
|
|
203
|
+
total: { type: 'number', const: 465.16 },
|
|
204
|
+
express: { type: 'boolean', const: false },
|
|
205
|
+
},
|
|
206
|
+
required: ['orderId', 'customer', 'items', 'total', 'express'],
|
|
207
|
+
additionalProperties: false,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: 'json_shape station raining at a whole temperature',
|
|
212
|
+
taskType: 'json_shape',
|
|
213
|
+
spec: {
|
|
214
|
+
instruction: SHAPE_INSTRUCTION,
|
|
215
|
+
input: 'The Vienna station reads 42.0 C with 100 percent humidity, and it is raining.',
|
|
216
|
+
output: SHAPE_OUTPUT_3,
|
|
217
|
+
},
|
|
218
|
+
answer: '{"station":"Vienna","tempC":42,"humidity":100,"raining":true}',
|
|
219
|
+
sha256: '98ca8812f15404b81cd12653dff3ae03bce6a804c19451ca34c12ea8f68a95cc',
|
|
220
|
+
jsonSchema: {
|
|
221
|
+
type: 'object',
|
|
222
|
+
properties: {
|
|
223
|
+
station: { type: 'string', const: 'Vienna' },
|
|
224
|
+
tempC: { type: 'number', const: 42 },
|
|
225
|
+
humidity: { type: 'integer', const: 100 },
|
|
226
|
+
raining: { type: 'boolean', const: true },
|
|
227
|
+
},
|
|
228
|
+
required: ['station', 'tempC', 'humidity', 'raining'],
|
|
229
|
+
additionalProperties: false,
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: 'json_shape station below zero',
|
|
234
|
+
taskType: 'json_shape',
|
|
235
|
+
spec: {
|
|
236
|
+
instruction: SHAPE_INSTRUCTION,
|
|
237
|
+
input: 'The Oslo station reads -5.5 C with 5 percent humidity, and it is not raining.',
|
|
238
|
+
output: SHAPE_OUTPUT_3,
|
|
239
|
+
},
|
|
240
|
+
answer: '{"station":"Oslo","tempC":-5.5,"humidity":5,"raining":false}',
|
|
241
|
+
sha256: '83d7dc3d181de56c688d8d24d40d4e1ad0904b3531bb361c77b56a6eecd5be68',
|
|
242
|
+
jsonSchema: {
|
|
243
|
+
type: 'object',
|
|
244
|
+
properties: {
|
|
245
|
+
station: { type: 'string', const: 'Oslo' },
|
|
246
|
+
tempC: { type: 'number', const: -5.5 },
|
|
247
|
+
humidity: { type: 'integer', const: 5 },
|
|
248
|
+
raining: { type: 'boolean', const: false },
|
|
249
|
+
},
|
|
250
|
+
required: ['station', 'tempC', 'humidity', 'raining'],
|
|
251
|
+
additionalProperties: false,
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: 'json_shape station at zero',
|
|
256
|
+
taskType: 'json_shape',
|
|
257
|
+
spec: {
|
|
258
|
+
instruction: SHAPE_INSTRUCTION,
|
|
259
|
+
input: 'The Oslo station reads 0.0 C with 50 percent humidity, and it is raining.',
|
|
260
|
+
output: SHAPE_OUTPUT_3,
|
|
261
|
+
},
|
|
262
|
+
answer: '{"station":"Oslo","tempC":0,"humidity":50,"raining":true}',
|
|
263
|
+
sha256: '90e2aebf3a32bc59b0d28dd139ffc236145d5587f6c6fba06a90b581fb1b872b',
|
|
264
|
+
jsonSchema: {
|
|
265
|
+
type: 'object',
|
|
266
|
+
properties: {
|
|
267
|
+
station: { type: 'string', const: 'Oslo' },
|
|
268
|
+
tempC: { type: 'number', const: 0 },
|
|
269
|
+
humidity: { type: 'integer', const: 50 },
|
|
270
|
+
raining: { type: 'boolean', const: true },
|
|
271
|
+
},
|
|
272
|
+
required: ['station', 'tempC', 'humidity', 'raining'],
|
|
273
|
+
additionalProperties: false,
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: 'json_shape station at the coldest draw',
|
|
278
|
+
taskType: 'json_shape',
|
|
279
|
+
spec: {
|
|
280
|
+
instruction: SHAPE_INSTRUCTION,
|
|
281
|
+
input: 'The Accra station reads -15.0 C with 99 percent humidity, and it is not raining.',
|
|
282
|
+
output: SHAPE_OUTPUT_3,
|
|
283
|
+
},
|
|
284
|
+
answer: '{"station":"Accra","tempC":-15,"humidity":99,"raining":false}',
|
|
285
|
+
sha256: '3e70b7c72ca7dabf20ac5b4f6b40cf35b9217a0fe4a0580f58953c21217017b7',
|
|
286
|
+
jsonSchema: {
|
|
287
|
+
type: 'object',
|
|
288
|
+
properties: {
|
|
289
|
+
station: { type: 'string', const: 'Accra' },
|
|
290
|
+
tempC: { type: 'number', const: -15 },
|
|
291
|
+
humidity: { type: 'integer', const: 99 },
|
|
292
|
+
raining: { type: 'boolean', const: false },
|
|
293
|
+
},
|
|
294
|
+
required: ['station', 'tempC', 'humidity', 'raining'],
|
|
295
|
+
additionalProperties: false,
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
];
|
package/dist/top-dimensions.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type Dimension } from './dimensions.js';
|
|
2
2
|
export type TopDimension = {
|
|
3
|
-
dimension:
|
|
3
|
+
dimension: Dimension;
|
|
4
4
|
value: number;
|
|
5
5
|
};
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function topDimensions(scores: readonly {
|
|
7
7
|
dimension: string;
|
|
8
8
|
value: number | null;
|
|
9
9
|
}[], count: number): TopDimension[];
|
package/dist/top-dimensions.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import { BaseDimension } from './dimensions.js';
|
|
2
|
-
|
|
3
|
-
//
|
|
4
|
-
// first
|
|
5
|
-
|
|
1
|
+
import { BaseDimension, COMPETENCE_DIMENSIONS, } from './dimensions.js';
|
|
2
|
+
import { SAFETY_MEASURED } from './standing.js';
|
|
3
|
+
// Every dimension a ranking looks at, in the fixed order ties keep. The base
|
|
4
|
+
// dimensions first, then the eight competence categories in stored order
|
|
5
|
+
// (RT-3, D-UI-12), so math ranks after operations on a tie. A key the
|
|
6
|
+
// issuer no longer writes, competence per task type, is never ranked, and
|
|
7
|
+
// neither is safety while SAFETY_MEASURED is off (VOU-436), whatever value
|
|
8
|
+
// an answer carries.
|
|
9
|
+
const RANKED = [
|
|
10
|
+
...BaseDimension.options.filter((d) => d !== 'safety' || SAFETY_MEASURED),
|
|
11
|
+
...COMPETENCE_DIMENSIONS,
|
|
12
|
+
];
|
|
13
|
+
// Dimensions with a value, highest first. Ties keep the order of RANKED.
|
|
14
|
+
// Callers that want trust only filter with isTrustDimension first.
|
|
15
|
+
export function topDimensions(scores, count) {
|
|
6
16
|
const ranked = [];
|
|
7
|
-
for (const d of
|
|
17
|
+
for (const d of RANKED) {
|
|
8
18
|
const value = scores.find((s) => s.dimension === d)?.value;
|
|
9
19
|
if (typeof value === 'number')
|
|
10
20
|
ranked.push({ dimension: d, value });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sealkeeper/schema",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Zod schemas, event taxonomy and signing helpers for SealKeeper.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"default": "./dist/index.js"
|
|
19
19
|
},
|
|
20
20
|
"./conformance": {
|
|
21
|
-
"types": "./dist/
|
|
22
|
-
"default": "./dist/
|
|
21
|
+
"types": "./dist/conformance.d.ts",
|
|
22
|
+
"default": "./dist/conformance.js"
|
|
23
23
|
},
|
|
24
24
|
"./db": {
|
|
25
25
|
"types": "./dist/db/index.d.ts",
|