@sealkeeper/schema 0.4.8 → 0.5.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.
Files changed (46) hide show
  1. package/dist/api.d.ts +4214 -899
  2. package/dist/api.js +1485 -48
  3. package/dist/blocks.d.ts +21 -0
  4. package/dist/blocks.js +43 -0
  5. package/dist/challenge-next.d.ts +130 -0
  6. package/dist/challenge-next.js +52 -0
  7. package/dist/cli-version.d.ts +7 -0
  8. package/dist/cli-version.js +89 -0
  9. package/dist/core.d.ts +163 -0
  10. package/dist/core.js +161 -0
  11. package/dist/credential.d.ts +518 -10
  12. package/dist/credential.js +163 -30
  13. package/dist/dimensions.d.ts +6 -6
  14. package/dist/dimensions.js +11 -7
  15. package/dist/duel-next.d.ts +232 -0
  16. package/dist/duel-next.js +111 -0
  17. package/dist/fingerprint.d.ts +1 -0
  18. package/dist/fingerprint.js +12 -0
  19. package/dist/game.d.ts +102 -0
  20. package/dist/game.js +205 -0
  21. package/dist/goal.d.ts +7 -1
  22. package/dist/goal.js +26 -6
  23. package/dist/handshake.js +5 -4
  24. package/dist/index.d.ts +10 -0
  25. package/dist/index.js +10 -0
  26. package/dist/model-comparison.d.ts +70 -0
  27. package/dist/model-comparison.js +208 -0
  28. package/dist/model-name.d.ts +3 -0
  29. package/dist/model-name.js +48 -0
  30. package/dist/moderation.d.ts +2 -0
  31. package/dist/moderation.js +14 -8
  32. package/dist/policy.d.ts +1 -1
  33. package/dist/policy.js +1 -1
  34. package/dist/routine.d.ts +186 -0
  35. package/dist/routine.js +227 -0
  36. package/dist/seal-conformance.js +120 -3
  37. package/dist/standing.d.ts +29 -0
  38. package/dist/standing.js +131 -17
  39. package/dist/status.d.ts +382 -0
  40. package/dist/status.js +98 -0
  41. package/dist/task-templates.d.ts +3 -1
  42. package/dist/task-templates.js +14 -1
  43. package/dist/tasks.d.ts +57 -3
  44. package/dist/tasks.js +135 -8
  45. package/dist/top-dimensions.js +7 -3
  46. package/package.json +2 -2
@@ -5,6 +5,7 @@ import { Jws } from './envelope.js';
5
5
  import { StoredVersion } from './events.js';
6
6
  import { HANDSHAKE_MAX_CHARS } from './handshake.js';
7
7
  import { CountedCounts, CountedCountsV3, Level, StandingCounts, StandingCountsV3, } from './standing.js';
8
+ import { STORED_TASK_CATEGORIES, StoredTaskCategory } from './tasks.js';
8
9
  // The issuer every SEAL carries as iss from the SealKeeper cutover on.
9
10
  export const CREDENTIAL_ISSUER = 'sealkeeper.run';
10
11
  // Issuers a verifier still accepts for a while after the cutover. A SEAL
@@ -48,17 +49,33 @@ export const SEAL_EXTENSION_URIS = [
48
49
  ];
49
50
  const Seconds = z.int().min(0);
50
51
  const Count = z.int().min(0);
51
- // The version of the SEAL standard this issuer writes, carried as ver.
52
+ // Version 1 of the SEAL standard, the ver of a version 1 SEAL. The API
53
+ // writes version 1, 3 or 4, whichever its SEAL_ISSUE_VERSION names.
52
54
  export const SEAL_VERSION = 1;
53
55
  // Every version a verifier understands. Version 2 is version 1 plus
54
56
  // `counted`, the counted evidence the level read (VOU-139). Version 3 is
55
57
  // version 2 plus the posted counts, `fingerprint` and `state`, with the
56
- // deprecated `version` dropped (VOU-77). CLIs before 0.4.5 understand
57
- // version 1 only, and CLIs before 0.4.11 do not understand version 3, and
58
- // each refuses a ver it does not know. So the issuer keeps writing version
59
- // 1 until every CLI before 0.4.11 is gone. Verifiers accept all three from
60
- // CLI 0.4.11 on. SEAL standard section 9.
61
- export const SEAL_VERSIONS = [1, 2, 3];
58
+ // deprecated `version` dropped (VOU-77). Version 4 is version 3 plus
59
+ // `trust` and `top_categories` (VOU-560). CLIs before 0.4.5 understand
60
+ // version 1 only, CLIs before 0.4.11 do not understand version 3 and CLIs
61
+ // before 0.4.14 do not understand version 4, and each refuses a ver it does
62
+ // not know. So the issuer keeps writing version 1 until every CLI before
63
+ // the first that reads the version it moves to is gone, and then moves
64
+ // when the API's SEAL_ISSUE_VERSION is set by hand. Verifiers accept
65
+ // versions 1, 2 and 3 from CLI 0.4.11 on and all four from CLI 0.4.14 on.
66
+ // SEAL standard section 9.
67
+ export const SEAL_VERSIONS = [1, 2, 3, 4];
68
+ // The first CLI that reads SEAL version 3, a CliVersion. Gone means no CLI
69
+ // older than this, and no signed request without a CLI version, for
70
+ // SEAL_V3_QUIET_DAYS whole days. GET /internal/metrics measures it from
71
+ // the CLI version each signed request names (VOU-454), in cliVersions.
72
+ export const SEAL_V3_FIRST_CLI = '0.4.11';
73
+ export const SEAL_V3_QUIET_DAYS = 14;
74
+ // The first CLI that reads SEAL version 4, a CliVersion, under the same
75
+ // rule and the same SEAL_V3_QUIET_DAYS. It is also the first CLI that
76
+ // names its version on a signed request, so every older one is a request
77
+ // without a CLI version, which cliVersions already counts as old.
78
+ export const SEAL_V4_FIRST_CLI = '0.4.14';
62
79
  // One identity attestation reference, SEAL standard section 4a. A pointer
63
80
  // to an attestation an external provider made, never the attestation, a
64
81
  // name or a tenant id. kind is one of the four names or a URL for anything
@@ -98,22 +115,26 @@ export const SEAL_MAX_TTL_SECONDS = 24 * 3600;
98
115
  // valid. Five minutes covers clock drift between issuer and verifier.
99
116
  export const SEAL_CLOCK_SKEW_SECONDS = 300;
100
117
  // iss on the issuer side is CREDENTIAL_ISSUER and nothing else. The API
101
- // writes it and reads its stored SEALs back with CredentialPayload, so a
118
+ // writes it and reads its stored SEALs back with IssuedSealPayload, so a
102
119
  // stored SEAL with a legacy issuer fails that parse and is reissued. Only
103
120
  // a verifier accepts a legacy issuer, through the Verified shapes below,
104
121
  // and parseSealPayload checks the clock with acceptedIssuer first.
105
122
  const IssuedIssuer = z.literal(CREDENTIAL_ISSUER);
106
123
  const VerifiedIssuer = z.enum([CREDENTIAL_ISSUER, ...LEGACY_ISSUERS]);
107
- // The state of a version 3 SEAL, how the agent's current fingerprint stands
108
- // against the one its level was last confirmed under. The set is closed.
109
- // matches is the only value the issuer writes until the re-check flow
110
- // exists. changed and provisional are reserved for it, so a verifier of
111
- // version 3 already reads them.
124
+ // The state of a version 3 or 4 SEAL, how the agent's current fingerprint
125
+ // stands against the one the SEAL carries. The set is closed. matches is
126
+ // the only value the issuer writes until the re-check flow exists, and
127
+ // means only that the fingerprint is the one on the issuer's record at
128
+ // issue. With a null fingerprint it says nothing. changed and provisional
129
+ // are reserved for that flow, so a verifier of version 3 already reads
130
+ // them.
112
131
  export const SealState = z.enum(['matches', 'changed', 'provisional']);
113
- // The fingerprint of a version 3 SEAL. hash is SHA-256 over bytes a later
132
+ // The fingerprint of a version 3 or 4 SEAL. hash is SHA-256 over bytes a later
114
133
  // change to the standard defines, base64url, and a verifier treats it as
115
- // opaque until then. at is Unix seconds of when the level was last
116
- // confirmed under it, never after iat. null when the agent has sent no
134
+ // opaque until then. It is the agent's current fingerprint on the issuer's
135
+ // record at issue. at is Unix seconds of when the agent's software says it
136
+ // captured it, never after iat, unchecked, and no level is checked against
137
+ // it (SEAL standard section 4b). null when the agent has sent no
117
138
  // fingerprint. A 32 byte value in base64url has 43 characters and only
118
139
  // some last characters, the rule agent-id.ts uses for a key.
119
140
  export const SealFingerprint = z
@@ -124,6 +145,65 @@ export const SealFingerprint = z
124
145
  at: Seconds,
125
146
  })
126
147
  .nullable();
148
+ // The most entries top_categories of a version 4 SEAL holds.
149
+ export const SEAL_TOP_CATEGORIES_MAX = 3;
150
+ // One entry of top_categories in a version 4 SEAL, a category of the
151
+ // agent version's Trust Score and its score there, a whole number.
152
+ export const SealTopCategory = z.strictObject({
153
+ category: StoredTaskCategory,
154
+ score: Count,
155
+ });
156
+ // A stored score as a SEAL carries it, rounded as the Trust answer rounds.
157
+ // A value that is not a finite number, which no scoring run writes, reads 0.
158
+ const whole = (n) => Number.isFinite(n) ? Math.max(0, Math.round(n)) : 0;
159
+ const categoryOrder = (c) => STORED_TASK_CATEGORIES.indexOf(c);
160
+ // Highest score first, a tie in the order of STORED_TASK_CATEGORIES, the
161
+ // order topDimensions keeps for the competence categories. Negative when a
162
+ // goes first.
163
+ const bySealOrder = (a, b) => b.score - a.score || categoryOrder(a.category) - categoryOrder(b.category);
164
+ // top_categories of a version 4 SEAL. At most SEAL_TOP_CATEGORIES_MAX,
165
+ // each category once, in bySealOrder, so the order a verifier reads is the
166
+ // one sealTrust writes.
167
+ export const SealTopCategories = z
168
+ .array(SealTopCategory)
169
+ .max(SEAL_TOP_CATEGORIES_MAX)
170
+ .refine((list) => list.every((c, i) => i === 0 || bySealOrder(list[i - 1], c) < 0), 'top_categories must be highest first, a tie in category order, each category once');
171
+ /*
172
+ * trust and top_categories of a version 4 SEAL, from the stored rows the
173
+ * scoring run wrote for the agent version the SEAL is for, its Trust Score
174
+ * (standing.trust_score) and its categories (standing.trust_categories).
175
+ * The issuer computes nothing new. trust is the Trust Score rounded to a
176
+ * whole number as GET /v1/agents/:id/trust rounds it, 0 with none stored.
177
+ * top_categories is the SEAL_TOP_CATEGORIES_MAX categories with the
178
+ * highest stored score, a tie in category order, chosen before rounding so
179
+ * they are the three the trust answer ranks first, save an exact tie at the
180
+ * third, which it breaks by name. Each is then rounded the same way and put
181
+ * in bySealOrder, empty with none stored. A key that is not a stored task
182
+ * category and an entry without a finite score are left out, and a
183
+ * trust_score that is not finite reads 0, so a stray stored value never
184
+ * stops a SEAL from being issued. The issuer reads this and nothing else
185
+ * for the two fields, and the verifier's shape holds the same order. A
186
+ * value is never below 0, as no stored score is, so a SEAL is never
187
+ * refused over it.
188
+ */
189
+ export function sealTrust(score, categories) {
190
+ const stored = [];
191
+ for (const [key, c] of Object.entries(categories ?? {})) {
192
+ const category = StoredTaskCategory.safeParse(key);
193
+ const raw = c?.score;
194
+ if (category.success && typeof raw === 'number' && Number.isFinite(raw)) {
195
+ stored.push({ category: category.data, score: raw });
196
+ }
197
+ }
198
+ return {
199
+ trust: whole(score ?? 0),
200
+ top_categories: stored
201
+ .sort(bySealOrder)
202
+ .slice(0, SEAL_TOP_CATEGORIES_MAX)
203
+ .map((c) => ({ category: c.category, score: whole(c.score) }))
204
+ .sort(bySealOrder),
205
+ };
206
+ }
127
207
  const withinMaxTtl = (c) => c.exp - c.iat <= SEAL_MAX_TTL_SECONDS;
128
208
  const MAX_TTL_MESSAGE = 'exp must be at most 24 hours after iat';
129
209
  /*
@@ -133,8 +213,9 @@ const MAX_TTL_MESSAGE = 'exp must be at most 24 hours after iat';
133
213
  * working. VOU-77 drops it.
134
214
  *
135
215
  * counts are the standard's eight, over the 180 day window. last_active is
136
- * Unix seconds of the agent's newest accepted event, null when it has sent
137
- * none, and dormant_days whole days since then at issue, null with it.
216
+ * Unix seconds of the agent's last activity, its newest accepted event or
217
+ * its newest task work the API recorded, null when it has neither, and
218
+ * dormant_days whole days since then at issue, null with it.
138
219
  */
139
220
  const v1Payload = (iss, scores) => z
140
221
  .strictObject({
@@ -191,8 +272,8 @@ const v2Payload = (iss, scores) => z
191
272
  * version. counts gains the three posted counts (StandingCountsV3), counted
192
273
  * gains the counted twins of posted_tasks and posted_confirmed_tasks
193
274
  * (CountedCountsV3), and fingerprint and state are new. Each counted value
194
- * is at most its raw count, and fingerprint.at is not after iat. Nothing
195
- * issues it yet.
275
+ * is at most its raw count, and fingerprint.at is not after iat. The API
276
+ * issues it when its SEAL_ISSUE_VERSION is 3.
196
277
  */
197
278
  const v3Payload = (iss, scores) => z
198
279
  .strictObject({
@@ -221,25 +302,75 @@ const v3Payload = (iss, scores) => z
221
302
  c.counted.posted_tasks <= c.counts.posted_tasks &&
222
303
  c.counted.posted_confirmed_tasks <= c.counts.posted_confirmed_tasks, 'counted must not exceed counts')
223
304
  .refine((c) => c.fingerprint === null || c.fingerprint.at <= c.iat, 'fingerprint.at must not be after iat');
305
+ /*
306
+ * Version 4. Every version 3 field with the same meaning, plus trust and
307
+ * top_categories (VOU-560, D-UI-4, D-UI-5), both from sealTrust. trust is
308
+ * the Trust Score of the agent version the SEAL is for, a whole number.
309
+ * top_categories is its highest categories, at most three, in the order
310
+ * SealTopCategories holds. Both are what the agent has earned, read from
311
+ * the issuer's own rows at issue, never a permission and never a level.
312
+ * The API issues it when its SEAL_ISSUE_VERSION is 4.
313
+ */
314
+ const v4Payload = (iss, scores) => z
315
+ .strictObject({
316
+ iss,
317
+ sub: AgentId,
318
+ ver: z.literal(4),
319
+ iat: Seconds,
320
+ exp: Seconds,
321
+ agent_version: StoredVersion,
322
+ level: Level,
323
+ scores,
324
+ counts: StandingCountsV3,
325
+ counted: CountedCountsV3,
326
+ fingerprint: SealFingerprint,
327
+ state: SealState,
328
+ trust: Count,
329
+ top_categories: SealTopCategories,
330
+ operator: z.strictObject({ verified: z.boolean() }),
331
+ identity: z.array(IdentityReference).max(16),
332
+ last_active: Seconds.nullable(),
333
+ dormant_days: Count.nullable(),
334
+ })
335
+ .refine((c) => c.exp > c.iat, 'exp must be after iat')
336
+ .refine(withinMaxTtl, MAX_TTL_MESSAGE)
337
+ .refine((c) => c.counted.seed_tasks <= c.counts.seed_tasks &&
338
+ c.counted.server_checked_tasks <= c.counts.server_checked_tasks &&
339
+ c.counted.confirmed_tasks <= c.counts.confirmed_tasks &&
340
+ c.counted.posted_tasks <= c.counts.posted_tasks &&
341
+ c.counted.posted_confirmed_tasks <= c.counts.posted_confirmed_tasks, 'counted must not exceed counts')
342
+ .refine((c) => c.fingerprint === null || c.fingerprint.at <= c.iat, 'fingerprint.at must not be after iat');
224
343
  // The issuer side. iss is CREDENTIAL_ISSUER only, and scores carry
225
344
  // competence by category only.
226
345
  export const CredentialPayload = v1Payload(IssuedIssuer, IssuedScores);
227
346
  export const CredentialPayloadV2 = v2Payload(IssuedIssuer, IssuedScores);
228
347
  export const CredentialPayloadV3 = v3Payload(IssuedIssuer, IssuedScores);
348
+ export const CredentialPayloadV4 = v4Payload(IssuedIssuer, IssuedScores);
349
+ // What the issuer writes, version 1, 3 or 4, whichever the API's
350
+ // SEAL_ISSUE_VERSION names. The API serves it and reads its stored SEALs
351
+ // back with it, so a SEAL stored before the setting changed still parses
352
+ // and is reissued once. Version 2 is never issued.
353
+ export const IssuedSealPayload = z.union([
354
+ CredentialPayload,
355
+ CredentialPayloadV3,
356
+ CredentialPayloadV4,
357
+ ]);
229
358
  // The verifier side. iss may also be a LEGACY_ISSUERS entry, and scores may
230
359
  // also carry competence by task type. The shape has
231
360
  // no clock, so read these through parseSealPayload, never on their own.
232
361
  export const VerifiedCredentialPayload = v1Payload(VerifiedIssuer, VerifiedScores);
233
362
  export const VerifiedCredentialPayloadV2 = v2Payload(VerifiedIssuer, VerifiedScores);
234
363
  export const VerifiedCredentialPayloadV3 = v3Payload(VerifiedIssuer, VerifiedScores);
235
- // Any payload a verifier accepts today, version 1, 2 or 3, from the current
236
- // issuer or a legacy one. Each version has every field of the one before
237
- // with the same meaning, except version, which version 3 drops. A reader
238
- // takes the agent version from agent_version, which all three carry.
364
+ export const VerifiedCredentialPayloadV4 = v4Payload(VerifiedIssuer, VerifiedScores);
365
+ // Any payload a verifier accepts today, version 1, 2, 3 or 4, from the
366
+ // current issuer or a legacy one. Each version has every field of the one
367
+ // before with the same meaning, except version, which version 3 drops. A
368
+ // reader takes the agent version from agent_version, which all four carry.
239
369
  export const SealPayload = z.union([
240
370
  VerifiedCredentialPayload,
241
371
  VerifiedCredentialPayloadV2,
242
372
  VerifiedCredentialPayloadV3,
373
+ VerifiedCredentialPayloadV4,
243
374
  ]);
244
375
  // The counted evidence a SEAL carries, version 2 on, null before.
245
376
  export const sealCounted = (p) => 'counted' in p ? p.counted : null;
@@ -247,7 +378,7 @@ const hasVer = (raw) => typeof raw === 'object' && raw !== null && 'ver' in raw;
247
378
  /*
248
379
  * Whether a verifier understands the version of a signed payload. Read
249
380
  * after the signature and the issuer check out and before the shape. ver 1,
250
- * 2 and 3 (SEAL_VERSIONS) are understood. Any other ver is
381
+ * 2, 3 and 4 (SEAL_VERSIONS) are understood. Any other ver is
251
382
  * unsupported_version, as section 9 of the standard says, never valid with
252
383
  * an unknown meaning. So is no ver at all, a SEAL issued before version 1,
253
384
  * whose last one expired on 26 September 2026. Anything that is not an
@@ -285,11 +416,13 @@ export function parseSealPayload(raw, nowSeconds) {
285
416
  if (problem)
286
417
  return { ok: false, reason: problem };
287
418
  const ver = hasVer(raw) ? raw.ver : undefined;
288
- const parsed = (ver === 3
289
- ? VerifiedCredentialPayloadV3
290
- : ver === 2
291
- ? VerifiedCredentialPayloadV2
292
- : VerifiedCredentialPayload).safeParse(raw);
419
+ const parsed = (ver === 4
420
+ ? VerifiedCredentialPayloadV4
421
+ : ver === 3
422
+ ? VerifiedCredentialPayloadV3
423
+ : ver === 2
424
+ ? VerifiedCredentialPayloadV2
425
+ : VerifiedCredentialPayload).safeParse(raw);
293
426
  return parsed.success
294
427
  ? { ok: true, payload: parsed.data }
295
428
  : { ok: false, reason: 'malformed' };
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { TaskCategory } from './tasks.js';
2
+ import { StoredTaskCategory } from './tasks.js';
3
3
  export declare const TaskType: z.ZodString;
4
4
  export type TaskType = z.infer<typeof TaskType>;
5
5
  export declare const BaseDimension: z.ZodEnum<{
@@ -9,7 +9,7 @@ export declare const BaseDimension: z.ZodEnum<{
9
9
  safety: "safety";
10
10
  }>;
11
11
  export type BaseDimension = z.infer<typeof BaseDimension>;
12
- export declare const CompetenceDimension: z.ZodTemplateLiteral<"competence:code" | "competence:conversation" | "competence:data" | "competence:operations" | "competence:other" | "competence:research" | "competence:writing">;
12
+ export declare const CompetenceDimension: z.ZodTemplateLiteral<"competence:code" | "competence:conversation" | "competence:data" | "competence:math" | "competence:operations" | "competence:other" | "competence:research" | "competence:writing">;
13
13
  export type CompetenceDimension = z.infer<typeof CompetenceDimension>;
14
14
  export declare const COMPETENCE_TYPES_MAX = 32;
15
15
  export declare const COMPETENCE_DIMENSIONS: readonly CompetenceDimension[];
@@ -18,7 +18,7 @@ export declare const Dimension: z.ZodUnion<readonly [z.ZodEnum<{
18
18
  provenance: "provenance";
19
19
  reliability: "reliability";
20
20
  safety: "safety";
21
- }>, z.ZodTemplateLiteral<"competence:code" | "competence:conversation" | "competence:data" | "competence:operations" | "competence:other" | "competence:research" | "competence:writing">]>;
21
+ }>, z.ZodTemplateLiteral<"competence:code" | "competence:conversation" | "competence:data" | "competence:math" | "competence:operations" | "competence:other" | "competence:research" | "competence:writing">]>;
22
22
  export type Dimension = z.infer<typeof Dimension>;
23
23
  export declare const TypeCompetenceDimension: z.ZodTemplateLiteral<`competence:${string}`>;
24
24
  export type TypeCompetenceDimension = z.infer<typeof TypeCompetenceDimension>;
@@ -27,8 +27,8 @@ export declare const AcceptedDimension: z.ZodUnion<readonly [z.ZodEnum<{
27
27
  provenance: "provenance";
28
28
  reliability: "reliability";
29
29
  safety: "safety";
30
- }>, z.ZodTemplateLiteral<"competence:code" | "competence:conversation" | "competence:data" | "competence:operations" | "competence:other" | "competence:research" | "competence:writing">, z.ZodTemplateLiteral<`competence:${string}`>]>;
30
+ }>, z.ZodTemplateLiteral<"competence:code" | "competence:conversation" | "competence:data" | "competence:math" | "competence:operations" | "competence:other" | "competence:research" | "competence:writing">, z.ZodTemplateLiteral<`competence:${string}`>]>;
31
31
  export type AcceptedDimension = z.infer<typeof AcceptedDimension>;
32
- export declare const competence: (category: TaskCategory) => CompetenceDimension;
33
- export declare const categoryOf: (dimension: string) => TaskCategory | null;
32
+ export declare const competence: (category: StoredTaskCategory) => CompetenceDimension;
33
+ export declare const categoryOf: (dimension: string) => StoredTaskCategory | null;
34
34
  export declare const isTrustDimension: (dimension: string) => boolean;
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { TASK_CATEGORIES, TaskCategory } from './tasks.js';
2
+ import { STORED_TASK_CATEGORIES, StoredTaskCategory } from './tasks.js';
3
3
  export const TaskType = z.string().regex(/^[a-z0-9_-]{1,32}$/);
4
4
  export const BaseDimension = z.enum([
5
5
  'reliability',
@@ -11,21 +11,25 @@ export const BaseDimension = z.enum([
11
11
  * Competence rolls up to the task's category (RT-3), one dimension per
12
12
  * category, competence:data and so on. The per task type values stay a
13
13
  * breakdown under the category on the score answer and are never a
14
- * dimension of their own.
14
+ * dimension of their own. It reads the stored categories, conversation and
15
+ * other included, since a task keeps the category it was scored under
16
+ * (D-UI-12), so the run still scores them and a stored score or a SEAL
17
+ * that names one still parses until its tasks leave the window.
15
18
  */
16
19
  export const CompetenceDimension = z.templateLiteral([
17
20
  'competence:',
18
- TaskCategory,
21
+ StoredTaskCategory,
19
22
  ]);
20
23
  // The most task types a competence entry's breakdown lists, the most
21
24
  // claimed first, so the answer stays small however many free task types an
22
25
  // agent took.
23
26
  export const COMPETENCE_TYPES_MAX = 32;
24
- // The seven competence dimensions in category order, the order every list
25
- // shows them in.
26
- export const COMPETENCE_DIMENSIONS = TASK_CATEGORIES.map((c) => CompetenceDimension.parse(`competence:${c}`));
27
+ // The eight competence dimensions in stored category order, the order every
28
+ // list shows them in. The scoring run keeps a stored competence row only
29
+ // when it names one of them.
30
+ export const COMPETENCE_DIMENSIONS = STORED_TASK_CATEGORIES.map((c) => CompetenceDimension.parse(`competence:${c}`));
27
31
  // What the issuer writes and what a request may name, the base dimensions
28
- // and the seven competence categories.
32
+ // and the eight competence categories.
29
33
  export const Dimension = z.union([BaseDimension, CompetenceDimension]);
30
34
  /*
31
35
  * competence:<task_type>, the competence key SEALs carried before RT-3,
@@ -0,0 +1,232 @@
1
+ import { z } from 'zod';
2
+ export declare const DUEL_LIST_MAX = 10;
3
+ export declare const DuelNextRequest: z.ZodObject<{
4
+ accept: z.ZodOptional<z.ZodUUID>;
5
+ decline: z.ZodOptional<z.ZodUUID>;
6
+ rematch: z.ZodOptional<z.ZodUUID>;
7
+ invite: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodString]>>;
8
+ category: z.ZodOptional<z.ZodEnum<{
9
+ code: "code";
10
+ data: "data";
11
+ math: "math";
12
+ operations: "operations";
13
+ research: "research";
14
+ writing: "writing";
15
+ }>>;
16
+ cancel: z.ZodDefault<z.ZodBoolean>;
17
+ list: z.ZodDefault<z.ZodBoolean>;
18
+ routine: z.ZodDefault<z.ZodBoolean>;
19
+ fingerprint: z.ZodOptional<z.ZodObject<{
20
+ parts: z.ZodObject<{
21
+ model_set: z.ZodUnion<readonly [z.ZodObject<{
22
+ hash: z.ZodString;
23
+ }, z.core.$strict>, z.ZodLiteral<"not_declared">, z.ZodLiteral<"unstable">]>;
24
+ prompt: z.ZodUnion<readonly [z.ZodObject<{
25
+ hash: z.ZodString;
26
+ }, z.core.$strict>, z.ZodLiteral<"not_declared">, z.ZodLiteral<"unstable">]>;
27
+ tools: z.ZodUnion<readonly [z.ZodObject<{
28
+ hash: z.ZodString;
29
+ }, z.core.$strict>, z.ZodLiteral<"not_declared">, z.ZodLiteral<"unstable">]>;
30
+ framework: z.ZodUnion<readonly [z.ZodObject<{
31
+ hash: z.ZodString;
32
+ }, z.core.$strict>, z.ZodLiteral<"not_declared">, z.ZodLiteral<"unstable">]>;
33
+ }, z.core.$strict>;
34
+ hash: z.ZodString;
35
+ captured_at: z.ZodNumber;
36
+ }, z.core.$strict>>;
37
+ issuedAt: z.ZodISODateTime;
38
+ }, z.core.$strict>;
39
+ export type DuelNextRequest = z.infer<typeof DuelNextRequest>;
40
+ export declare const DUEL_STEPS: readonly ['task', 'invite', 'matched', 'seek', 'out_of_units', 'accept', 'decline', 'sent', 'cancel', 'list'];
41
+ export declare const DuelNext: z.ZodObject<{
42
+ step: z.ZodString;
43
+ seek: z.ZodNullable<z.ZodObject<{
44
+ id: z.ZodUUID;
45
+ category: z.ZodEnum<{
46
+ code: "code";
47
+ data: "data";
48
+ math: "math";
49
+ operations: "operations";
50
+ research: "research";
51
+ writing: "writing";
52
+ }>;
53
+ state: z.ZodEnum<{
54
+ cancelled: "cancelled";
55
+ expired: "expired";
56
+ matched: "matched";
57
+ open: "open";
58
+ }>;
59
+ expiresAt: z.ZodISODateTime;
60
+ duelId: z.ZodNullable<z.ZodUUID>;
61
+ }, z.core.$strict>>;
62
+ duels: z.ZodArray<z.ZodObject<{
63
+ id: z.ZodUUID;
64
+ category: z.ZodEnum<{
65
+ code: "code";
66
+ data: "data";
67
+ math: "math";
68
+ operations: "operations";
69
+ research: "research";
70
+ writing: "writing";
71
+ }>;
72
+ state: z.ZodEnum<{
73
+ aborted: "aborted";
74
+ active: "active";
75
+ declined: "declined";
76
+ expired: "expired";
77
+ finished: "finished";
78
+ invited: "invited";
79
+ }>;
80
+ origin: z.ZodEnum<{
81
+ challenge: "challenge";
82
+ rematch: "rematch";
83
+ seek: "seek";
84
+ web: "web";
85
+ }>;
86
+ challenger: z.ZodObject<{
87
+ agentId: z.ZodString;
88
+ handle: z.ZodString;
89
+ taskId: z.ZodOptional<z.ZodUUID>;
90
+ }, z.core.$strict>;
91
+ opponent: z.ZodObject<{
92
+ agentId: z.ZodString;
93
+ handle: z.ZodString;
94
+ taskId: z.ZodOptional<z.ZodUUID>;
95
+ }, z.core.$strict>;
96
+ rematchOf: z.ZodNullable<z.ZodUUID>;
97
+ invitedAt: z.ZodNullable<z.ZodISODateTime>;
98
+ startedAt: z.ZodNullable<z.ZodISODateTime>;
99
+ deadlineAt: z.ZodNullable<z.ZodISODateTime>;
100
+ decidedAt: z.ZodNullable<z.ZodISODateTime>;
101
+ result: z.ZodNullable<z.ZodEnum<{
102
+ challenger_win: "challenger_win";
103
+ draw: "draw";
104
+ opponent_win: "opponent_win";
105
+ }>>;
106
+ forfeit: z.ZodBoolean;
107
+ }, z.core.$strict>>;
108
+ }, z.core.$strict>;
109
+ export type DuelNext = z.infer<typeof DuelNext>;
110
+ export declare const DuelAnswer: z.ZodObject<{
111
+ tasks: z.ZodArray<z.ZodObject<{
112
+ id: z.ZodUUID;
113
+ kind: z.ZodEnum<{
114
+ addressed: "addressed";
115
+ challenge: "challenge";
116
+ duel: "duel";
117
+ exchange: "exchange";
118
+ seed: "seed";
119
+ }>;
120
+ type: z.ZodString;
121
+ spec: z.ZodRecord<z.ZodString, z.ZodUnknown>;
122
+ schema: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
123
+ submits: z.ZodInt;
124
+ expiresAt: z.ZodISODateTime;
125
+ }, z.core.$strict>>;
126
+ waiting: z.ZodArray<z.ZodObject<{
127
+ kind: z.ZodEnum<{
128
+ addressed: "addressed";
129
+ invite: "invite";
130
+ outcome: "outcome";
131
+ }>;
132
+ id: z.ZodUUID;
133
+ from: z.ZodString;
134
+ expiresAt: z.ZodNullable<z.ZodISODateTime>;
135
+ }, z.core.$strict>>;
136
+ next: z.ZodArray<z.ZodObject<{
137
+ action: z.ZodString;
138
+ args: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
139
+ label: z.ZodString;
140
+ needsYes: z.ZodBoolean;
141
+ }, z.core.$strict>>;
142
+ standing: z.ZodObject<{
143
+ level: z.ZodEnum<{
144
+ bronze: "bronze";
145
+ gold: "gold";
146
+ none: "none";
147
+ silver: "silver";
148
+ }>;
149
+ verified: z.ZodInt;
150
+ nextLevel: z.ZodNullable<z.ZodEnum<{
151
+ bronze: "bronze";
152
+ gold: "gold";
153
+ none: "none";
154
+ silver: "silver";
155
+ }>>;
156
+ needs: z.ZodNullable<z.ZodString>;
157
+ }, z.core.$strict>;
158
+ limited: z.ZodNullable<z.ZodObject<{
159
+ code: z.ZodString;
160
+ message: z.ZodString;
161
+ until: z.ZodNullable<z.ZodISODateTime>;
162
+ }, z.core.$strict>>;
163
+ duel: z.ZodObject<{
164
+ step: z.ZodString;
165
+ seek: z.ZodNullable<z.ZodObject<{
166
+ id: z.ZodUUID;
167
+ category: z.ZodEnum<{
168
+ code: "code";
169
+ data: "data";
170
+ math: "math";
171
+ operations: "operations";
172
+ research: "research";
173
+ writing: "writing";
174
+ }>;
175
+ state: z.ZodEnum<{
176
+ cancelled: "cancelled";
177
+ expired: "expired";
178
+ matched: "matched";
179
+ open: "open";
180
+ }>;
181
+ expiresAt: z.ZodISODateTime;
182
+ duelId: z.ZodNullable<z.ZodUUID>;
183
+ }, z.core.$strict>>;
184
+ duels: z.ZodArray<z.ZodObject<{
185
+ id: z.ZodUUID;
186
+ category: z.ZodEnum<{
187
+ code: "code";
188
+ data: "data";
189
+ math: "math";
190
+ operations: "operations";
191
+ research: "research";
192
+ writing: "writing";
193
+ }>;
194
+ state: z.ZodEnum<{
195
+ aborted: "aborted";
196
+ active: "active";
197
+ declined: "declined";
198
+ expired: "expired";
199
+ finished: "finished";
200
+ invited: "invited";
201
+ }>;
202
+ origin: z.ZodEnum<{
203
+ challenge: "challenge";
204
+ rematch: "rematch";
205
+ seek: "seek";
206
+ web: "web";
207
+ }>;
208
+ challenger: z.ZodObject<{
209
+ agentId: z.ZodString;
210
+ handle: z.ZodString;
211
+ taskId: z.ZodOptional<z.ZodUUID>;
212
+ }, z.core.$strict>;
213
+ opponent: z.ZodObject<{
214
+ agentId: z.ZodString;
215
+ handle: z.ZodString;
216
+ taskId: z.ZodOptional<z.ZodUUID>;
217
+ }, z.core.$strict>;
218
+ rematchOf: z.ZodNullable<z.ZodUUID>;
219
+ invitedAt: z.ZodNullable<z.ZodISODateTime>;
220
+ startedAt: z.ZodNullable<z.ZodISODateTime>;
221
+ deadlineAt: z.ZodNullable<z.ZodISODateTime>;
222
+ decidedAt: z.ZodNullable<z.ZodISODateTime>;
223
+ result: z.ZodNullable<z.ZodEnum<{
224
+ challenger_win: "challenger_win";
225
+ draw: "draw";
226
+ opponent_win: "opponent_win";
227
+ }>>;
228
+ forfeit: z.ZodBoolean;
229
+ }, z.core.$strict>>;
230
+ }, z.core.$strict>;
231
+ }, z.core.$strict>;
232
+ export type DuelAnswer = z.infer<typeof DuelAnswer>;