@sealkeeper/schema 0.4.4 → 0.4.5
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/agent-name.d.ts +1 -1
- package/dist/agent-name.js +4 -4
- package/dist/api.d.ts +604 -27
- package/dist/api.js +207 -43
- package/dist/badge.d.ts +1 -0
- package/dist/badge.js +7 -0
- package/dist/db/agents.d.ts +70 -0
- package/dist/db/agents.js +18 -0
- package/dist/db/client.d.ts +341 -0
- package/dist/db/client.js +2 -0
- package/dist/db/events.js +7 -0
- package/dist/db/index.d.ts +16 -0
- package/dist/db/index.js +4 -0
- package/dist/db/migrate.js +5 -1
- package/dist/db/migrator.d.ts +3 -1
- package/dist/db/migrator.js +8 -2
- package/dist/db/operator-identities.d.ts +211 -0
- package/dist/db/operator-identities.js +49 -0
- package/dist/db/operator-level-grants.d.ts +109 -0
- package/dist/db/operator-level-grants.js +30 -0
- package/dist/db/operator-slugs.d.ts +92 -0
- package/dist/db/operator-slugs.js +25 -0
- package/dist/db/operators.d.ts +119 -0
- package/dist/db/operators.js +30 -2
- package/dist/db/standing.d.ts +1 -0
- package/dist/db/standing.js +2 -0
- package/dist/db/task-claim-failures.d.ts +143 -0
- package/dist/db/task-claim-failures.js +37 -0
- package/dist/db/tasks.d.ts +60 -0
- package/dist/db/tasks.js +13 -1
- package/dist/envelope.d.ts +3 -0
- package/dist/envelope.js +16 -11
- package/dist/goal.d.ts +62 -1
- package/dist/goal.js +70 -11
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/moderation.d.ts +28 -0
- package/dist/moderation.js +450 -0
- package/dist/operator-domains.d.ts +104 -0
- package/dist/operator-domains.js +85 -0
- package/dist/policy.d.ts +4 -0
- package/dist/policy.js +10 -0
- package/dist/runtime.d.ts +17 -0
- package/dist/runtime.js +61 -0
- package/dist/seal-conformance.js +2 -0
- package/dist/standing.d.ts +27 -8
- package/dist/standing.js +59 -22
- package/dist/tasks.d.ts +23 -1
- package/dist/tasks.js +29 -5
- package/package.json +1 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const DNS_RECORD_LABEL = "_sealkeeper";
|
|
3
|
+
export declare const DNS_RECORD_PREFIX = "sealkeeper-verify=";
|
|
4
|
+
export declare const DNS_IDENTITY_KIND = "https://sealkeeper.run/seal/identity/dns";
|
|
5
|
+
export declare const DNS_IDENTITY_PROVIDER = "https://sealkeeper.run";
|
|
6
|
+
export declare const OPERATOR_VERIFICATION: {
|
|
7
|
+
readonly graceDays: 14;
|
|
8
|
+
readonly recheckHours: 24;
|
|
9
|
+
readonly maxDomains: 5;
|
|
10
|
+
};
|
|
11
|
+
export declare const DomainName: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
|
|
12
|
+
export type DomainName = z.infer<typeof DomainName>;
|
|
13
|
+
export declare const AddDomainRequest: z.ZodObject<{
|
|
14
|
+
domain: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
export type AddDomainRequest = z.infer<typeof AddDomainRequest>;
|
|
17
|
+
export declare const DomainParams: z.ZodObject<{
|
|
18
|
+
id: z.ZodUUID;
|
|
19
|
+
}, z.core.$strict>;
|
|
20
|
+
export type DomainParams = z.infer<typeof DomainParams>;
|
|
21
|
+
export declare const DomainStatus: z.ZodEnum<{
|
|
22
|
+
lapsed: "lapsed";
|
|
23
|
+
lapsing: "lapsing";
|
|
24
|
+
pending: "pending";
|
|
25
|
+
verified: "verified";
|
|
26
|
+
}>;
|
|
27
|
+
export type DomainStatus = z.infer<typeof DomainStatus>;
|
|
28
|
+
export declare const OperatorDomain: z.ZodObject<{
|
|
29
|
+
id: z.ZodUUID;
|
|
30
|
+
domain: z.ZodString;
|
|
31
|
+
record: z.ZodObject<{
|
|
32
|
+
name: z.ZodString;
|
|
33
|
+
value: z.ZodString;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
status: z.ZodEnum<{
|
|
36
|
+
lapsed: "lapsed";
|
|
37
|
+
lapsing: "lapsing";
|
|
38
|
+
pending: "pending";
|
|
39
|
+
verified: "verified";
|
|
40
|
+
}>;
|
|
41
|
+
verifiedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
42
|
+
lastCheckedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
43
|
+
lapsedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
44
|
+
graceEndsAt: z.ZodNullable<z.ZodISODateTime>;
|
|
45
|
+
}, z.core.$strict>;
|
|
46
|
+
export type OperatorDomain = z.infer<typeof OperatorDomain>;
|
|
47
|
+
export declare const DomainsResponse: z.ZodObject<{
|
|
48
|
+
domains: z.ZodArray<z.ZodObject<{
|
|
49
|
+
id: z.ZodUUID;
|
|
50
|
+
domain: z.ZodString;
|
|
51
|
+
record: z.ZodObject<{
|
|
52
|
+
name: z.ZodString;
|
|
53
|
+
value: z.ZodString;
|
|
54
|
+
}, z.core.$strict>;
|
|
55
|
+
status: z.ZodEnum<{
|
|
56
|
+
lapsed: "lapsed";
|
|
57
|
+
lapsing: "lapsing";
|
|
58
|
+
pending: "pending";
|
|
59
|
+
verified: "verified";
|
|
60
|
+
}>;
|
|
61
|
+
verifiedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
62
|
+
lastCheckedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
63
|
+
lapsedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
64
|
+
graceEndsAt: z.ZodNullable<z.ZodISODateTime>;
|
|
65
|
+
}, z.core.$strict>>;
|
|
66
|
+
graceDays: z.ZodInt;
|
|
67
|
+
}, z.core.$strict>;
|
|
68
|
+
export type DomainsResponse = z.infer<typeof DomainsResponse>;
|
|
69
|
+
export declare const DomainLookup: z.ZodEnum<{
|
|
70
|
+
failed: "failed";
|
|
71
|
+
found: "found";
|
|
72
|
+
missing: "missing";
|
|
73
|
+
}>;
|
|
74
|
+
export type DomainLookup = z.infer<typeof DomainLookup>;
|
|
75
|
+
export declare const DomainCheckResponse: z.ZodObject<{
|
|
76
|
+
domain: z.ZodObject<{
|
|
77
|
+
id: z.ZodUUID;
|
|
78
|
+
domain: z.ZodString;
|
|
79
|
+
record: z.ZodObject<{
|
|
80
|
+
name: z.ZodString;
|
|
81
|
+
value: z.ZodString;
|
|
82
|
+
}, z.core.$strict>;
|
|
83
|
+
status: z.ZodEnum<{
|
|
84
|
+
lapsed: "lapsed";
|
|
85
|
+
lapsing: "lapsing";
|
|
86
|
+
pending: "pending";
|
|
87
|
+
verified: "verified";
|
|
88
|
+
}>;
|
|
89
|
+
verifiedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
90
|
+
lastCheckedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
91
|
+
lapsedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
92
|
+
graceEndsAt: z.ZodNullable<z.ZodISODateTime>;
|
|
93
|
+
}, z.core.$strict>;
|
|
94
|
+
lookup: z.ZodEnum<{
|
|
95
|
+
failed: "failed";
|
|
96
|
+
found: "found";
|
|
97
|
+
missing: "missing";
|
|
98
|
+
}>;
|
|
99
|
+
}, z.core.$strict>;
|
|
100
|
+
export type DomainCheckResponse = z.infer<typeof DomainCheckResponse>;
|
|
101
|
+
export declare const domainRecord: (domain: string, token: string) => {
|
|
102
|
+
name: string;
|
|
103
|
+
value: string;
|
|
104
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// Operator verification by DNS TXT (VOU-185), gold's operator_verified at
|
|
3
|
+
// launch. The operator adds a domain on the account page, puts a TXT
|
|
4
|
+
// record at DNS_RECORD_LABEL.<domain> holding DNS_RECORD_PREFIX<token>, and
|
|
5
|
+
// SealKeeper checks it. The API's routes live under /v1/me/domains.
|
|
6
|
+
// The record name is this label, a dot and the domain.
|
|
7
|
+
export const DNS_RECORD_LABEL = '_sealkeeper';
|
|
8
|
+
// The record value is this prefix and the token.
|
|
9
|
+
export const DNS_RECORD_PREFIX = 'sealkeeper-verify=';
|
|
10
|
+
// The kind and provider of a DNS identity in a SEAL, SEAL standard section
|
|
11
|
+
// 4a. kind is a URL, since dns is none of the four named kinds. SealKeeper
|
|
12
|
+
// checked the record, so it is the provider.
|
|
13
|
+
export const DNS_IDENTITY_KIND = 'https://sealkeeper.run/seal/identity/dns';
|
|
14
|
+
export const DNS_IDENTITY_PROVIDER = 'https://sealkeeper.run';
|
|
15
|
+
// How a verified domain lapses (26 September 2026, the grace period still
|
|
16
|
+
// open). SealKeeper checks every verified domain again about every
|
|
17
|
+
// recheckHours hours. A check that misses the record starts graceDays days
|
|
18
|
+
// of grace, in which the operator stays verified and the goal warns, and
|
|
19
|
+
// operator_verified goes false when it ends. A check that finds the record
|
|
20
|
+
// again ends the grace. maxDomains is how many domains one operator may
|
|
21
|
+
// add. The scoring job and the API read these, so they live here.
|
|
22
|
+
export const OPERATOR_VERIFICATION = {
|
|
23
|
+
graceDays: 14,
|
|
24
|
+
recheckHours: 24,
|
|
25
|
+
maxDomains: 5,
|
|
26
|
+
};
|
|
27
|
+
// A host name in ASCII, lower case, at least two labels, the last starting
|
|
28
|
+
// with a letter so an IP address never passes. An IDN goes in as its
|
|
29
|
+
// xn-- form. A trailing dot is dropped first.
|
|
30
|
+
const HOST = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
31
|
+
export const DomainName = z
|
|
32
|
+
.string()
|
|
33
|
+
.trim()
|
|
34
|
+
.toLowerCase()
|
|
35
|
+
.max(254)
|
|
36
|
+
.transform((d) => d.replace(/\.$/, ''))
|
|
37
|
+
.pipe(z.string().regex(HOST, 'a domain such as example.com'));
|
|
38
|
+
// POST /v1/me/domains.
|
|
39
|
+
export const AddDomainRequest = z.strictObject({ domain: DomainName });
|
|
40
|
+
// POST /v1/me/domains/:id/check and DELETE /v1/me/domains/:id.
|
|
41
|
+
export const DomainParams = z.strictObject({ id: z.uuid() });
|
|
42
|
+
// pending, added and never found. verified, found at the last check.
|
|
43
|
+
// lapsing, missed since lapsedAt and still verified until graceEndsAt.
|
|
44
|
+
// lapsed, missed for the whole grace period and no longer verified.
|
|
45
|
+
export const DomainStatus = z.enum([
|
|
46
|
+
'pending',
|
|
47
|
+
'verified',
|
|
48
|
+
'lapsing',
|
|
49
|
+
'lapsed',
|
|
50
|
+
]);
|
|
51
|
+
const Timestamp = z.iso.datetime();
|
|
52
|
+
// One domain as its operator sees it, with the record to add. Private to
|
|
53
|
+
// the signed in operator.
|
|
54
|
+
export const OperatorDomain = z.strictObject({
|
|
55
|
+
id: z.uuid(),
|
|
56
|
+
domain: z.string().min(1).max(253),
|
|
57
|
+
record: z.strictObject({
|
|
58
|
+
name: z.string().min(1).max(300),
|
|
59
|
+
value: z.string().min(1).max(300),
|
|
60
|
+
}),
|
|
61
|
+
status: DomainStatus,
|
|
62
|
+
verifiedAt: Timestamp.nullable(),
|
|
63
|
+
lastCheckedAt: Timestamp.nullable(),
|
|
64
|
+
lapsedAt: Timestamp.nullable(),
|
|
65
|
+
graceEndsAt: Timestamp.nullable(),
|
|
66
|
+
});
|
|
67
|
+
// GET /v1/me/domains and the answer of POST /v1/me/domains.
|
|
68
|
+
export const DomainsResponse = z.strictObject({
|
|
69
|
+
domains: z.array(OperatorDomain),
|
|
70
|
+
graceDays: z.int().positive(),
|
|
71
|
+
});
|
|
72
|
+
// What one lookup of the record found. found, the token is there. missing,
|
|
73
|
+
// the name has no TXT record with it. failed, the lookup itself did not
|
|
74
|
+
// answer, so nothing is known.
|
|
75
|
+
export const DomainLookup = z.enum(['found', 'missing', 'failed']);
|
|
76
|
+
// POST /v1/me/domains/:id/check.
|
|
77
|
+
export const DomainCheckResponse = z.strictObject({
|
|
78
|
+
domain: OperatorDomain,
|
|
79
|
+
lookup: DomainLookup,
|
|
80
|
+
});
|
|
81
|
+
// The TXT record for a domain and a token.
|
|
82
|
+
export const domainRecord = (domain, token) => ({
|
|
83
|
+
name: `${DNS_RECORD_LABEL}.${domain}`,
|
|
84
|
+
value: `${DNS_RECORD_PREFIX}${token}`,
|
|
85
|
+
});
|
package/dist/policy.d.ts
ADDED
package/dist/policy.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// The versions of the terms of service and the privacy policy, as the
|
|
2
|
+
// "Last updated" date each page shows, YYYY-MM-DD. The single source of
|
|
3
|
+
// truth. The web renders both pages' dates from here and the API stamps them
|
|
4
|
+
// on an operator when it creates the row and on an agent when it registers,
|
|
5
|
+
// as what was accepted (VOU-121). The client never sends them. Change a date
|
|
6
|
+
// here when the matching page changes.
|
|
7
|
+
export const POLICY_VERSIONS = {
|
|
8
|
+
terms: '2026-09-27',
|
|
9
|
+
privacy: '2026-09-27',
|
|
10
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const RUNTIMES: readonly ['claude-code', 'codex', 'cursor', 'gemini-cli', 'openclaw', 'mastra', 'other', 'unknown'];
|
|
3
|
+
export declare const Runtime: z.ZodEnum<{
|
|
4
|
+
"claude-code": "claude-code";
|
|
5
|
+
codex: "codex";
|
|
6
|
+
cursor: "cursor";
|
|
7
|
+
"gemini-cli": "gemini-cli";
|
|
8
|
+
mastra: "mastra";
|
|
9
|
+
openclaw: "openclaw";
|
|
10
|
+
other: "other";
|
|
11
|
+
unknown: "unknown";
|
|
12
|
+
}>;
|
|
13
|
+
export type Runtime = z.infer<typeof Runtime>;
|
|
14
|
+
export declare const DEFAULT_RUNTIME: Runtime;
|
|
15
|
+
export declare const RUNTIME_LABELS: Readonly<Record<Runtime, string>>;
|
|
16
|
+
export declare const RUNTIME_NAMES: ReadonlySet<string>;
|
|
17
|
+
export declare function isRuntimeName(name: string): boolean;
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// What an agent runs in, such as Claude Code or Codex. Declared by the
|
|
3
|
+
// operator at registration or with a signed PATCH, never inferred from
|
|
4
|
+
// events, since events do not say which adapter sent them. `other` is a
|
|
5
|
+
// runtime not on this list, `unknown` is an agent that has not said, which
|
|
6
|
+
// is every agent registered before runtimes existed and every agent a CLI
|
|
7
|
+
// without runtimes registers.
|
|
8
|
+
export const RUNTIMES = [
|
|
9
|
+
'claude-code',
|
|
10
|
+
'codex',
|
|
11
|
+
'cursor',
|
|
12
|
+
'gemini-cli',
|
|
13
|
+
'openclaw',
|
|
14
|
+
'mastra',
|
|
15
|
+
'other',
|
|
16
|
+
'unknown',
|
|
17
|
+
];
|
|
18
|
+
export const Runtime = z.enum(RUNTIMES);
|
|
19
|
+
// The runtime an agent has until it says otherwise.
|
|
20
|
+
export const DEFAULT_RUNTIME = 'unknown';
|
|
21
|
+
// How a runtime reads in prose, on the web and in the CLI.
|
|
22
|
+
export const RUNTIME_LABELS = {
|
|
23
|
+
'claude-code': 'Claude Code',
|
|
24
|
+
codex: 'Codex',
|
|
25
|
+
cursor: 'Cursor',
|
|
26
|
+
'gemini-cli': 'Gemini CLI',
|
|
27
|
+
openclaw: 'OpenClaw',
|
|
28
|
+
mastra: 'Mastra',
|
|
29
|
+
other: 'Other',
|
|
30
|
+
unknown: 'Unknown',
|
|
31
|
+
};
|
|
32
|
+
// Names that say what an agent runs in rather than which agent it is, such
|
|
33
|
+
// as claude-code or codex. A soft list. The CLI nudges once when an agent
|
|
34
|
+
// is about to be registered under one, and keeping it is allowed. The API
|
|
35
|
+
// never refuses one, so the list can grow without breaking anybody.
|
|
36
|
+
export const RUNTIME_NAMES = new Set([
|
|
37
|
+
'aider',
|
|
38
|
+
'amp',
|
|
39
|
+
'claude',
|
|
40
|
+
'claude-code',
|
|
41
|
+
'cline',
|
|
42
|
+
'codex',
|
|
43
|
+
'codex-cli',
|
|
44
|
+
'continue',
|
|
45
|
+
'copilot',
|
|
46
|
+
'cursor',
|
|
47
|
+
'cursor-agent',
|
|
48
|
+
'devin',
|
|
49
|
+
'gemini',
|
|
50
|
+
'gemini-cli',
|
|
51
|
+
'goose',
|
|
52
|
+
'mastra',
|
|
53
|
+
'openclaw',
|
|
54
|
+
'opencode',
|
|
55
|
+
'roo-code',
|
|
56
|
+
'windsurf',
|
|
57
|
+
]);
|
|
58
|
+
// True when name is on the soft list above.
|
|
59
|
+
export function isRuntimeName(name) {
|
|
60
|
+
return RUNTIME_NAMES.has(name);
|
|
61
|
+
}
|
package/dist/seal-conformance.js
CHANGED
|
@@ -114,6 +114,8 @@ export async function sealConformanceCases() {
|
|
|
114
114
|
signed({ ...base, ver: undefined }),
|
|
115
115
|
'unsupported_version',
|
|
116
116
|
],
|
|
117
|
+
// Intended. Platinum is reserved on LADDER and is not a Level under ver
|
|
118
|
+
// 1 or 2 (standard, section 9). It becomes valid only with a ver bump.
|
|
117
119
|
[
|
|
118
120
|
'the wrong shape, a level not in the standard',
|
|
119
121
|
signed({ ...base, level: 'platinum' }),
|
package/dist/standing.d.ts
CHANGED
|
@@ -7,6 +7,25 @@ export declare const Level: z.ZodEnum<{
|
|
|
7
7
|
}>;
|
|
8
8
|
export type Level = z.infer<typeof Level>;
|
|
9
9
|
export declare const LEVEL_RANK: Record<Level, number>;
|
|
10
|
+
export declare const LADDER: readonly [{
|
|
11
|
+
readonly level: 'none';
|
|
12
|
+
readonly state: 'issued';
|
|
13
|
+
}, {
|
|
14
|
+
readonly level: 'bronze';
|
|
15
|
+
readonly state: 'issued';
|
|
16
|
+
}, {
|
|
17
|
+
readonly level: 'silver';
|
|
18
|
+
readonly state: 'issued';
|
|
19
|
+
}, {
|
|
20
|
+
readonly level: 'gold';
|
|
21
|
+
readonly state: 'issued';
|
|
22
|
+
}, {
|
|
23
|
+
readonly level: 'platinum';
|
|
24
|
+
readonly state: 'reserved';
|
|
25
|
+
}];
|
|
26
|
+
export type LadderLevel = (typeof LADDER)[number]['level'];
|
|
27
|
+
export type LadderState = (typeof LADDER)[number]['state'];
|
|
28
|
+
export declare const ISSUED_LEVELS: readonly Level[];
|
|
10
29
|
export declare const StandingCounts: z.ZodObject<{
|
|
11
30
|
events: z.ZodInt;
|
|
12
31
|
history_days: z.ZodInt;
|
|
@@ -45,9 +64,6 @@ export declare const LEVEL_THRESHOLDS: {
|
|
|
45
64
|
};
|
|
46
65
|
readonly silver: {
|
|
47
66
|
readonly verifiedTasks: 200;
|
|
48
|
-
readonly checkedOrConfirmed: 100;
|
|
49
|
-
readonly distinctOperators: 5;
|
|
50
|
-
readonly confirmedTasks: 25;
|
|
51
67
|
readonly historyDays: 30;
|
|
52
68
|
readonly reliability: 0.9;
|
|
53
69
|
readonly safety: 0.9;
|
|
@@ -56,18 +72,21 @@ export declare const LEVEL_THRESHOLDS: {
|
|
|
56
72
|
readonly modelDeclared: true;
|
|
57
73
|
};
|
|
58
74
|
readonly gold: {
|
|
59
|
-
readonly verifiedTasks:
|
|
60
|
-
readonly confirmedTasks:
|
|
61
|
-
readonly confirmedOperators:
|
|
75
|
+
readonly verifiedTasks: 200;
|
|
76
|
+
readonly confirmedTasks: 25;
|
|
77
|
+
readonly confirmedOperators: 3;
|
|
62
78
|
readonly historySpanDays: 90;
|
|
63
79
|
readonly activeDays: 60;
|
|
64
80
|
readonly reliability: 0.95;
|
|
65
81
|
readonly safety: 0.95;
|
|
66
|
-
readonly
|
|
82
|
+
readonly cleanDays: 180;
|
|
67
83
|
readonly operatorVerified: true;
|
|
68
|
-
readonly ratings: 10;
|
|
69
84
|
};
|
|
70
85
|
};
|
|
86
|
+
export declare const OPERATOR_SILVER_CAP: {
|
|
87
|
+
readonly agents: 5;
|
|
88
|
+
readonly days: 30;
|
|
89
|
+
};
|
|
71
90
|
export declare function dormantDays(lastActive: Date | null, now: Date): number | null;
|
|
72
91
|
export declare const isQuiet: (days: number | null) => boolean;
|
|
73
92
|
export declare const Standing: z.ZodObject<{
|
package/dist/standing.js
CHANGED
|
@@ -2,13 +2,33 @@ import { z } from 'zod';
|
|
|
2
2
|
// Standing levels from the SEAL standard, section 5, lowest first. none is
|
|
3
3
|
// below bronze. Every scored agent version has one.
|
|
4
4
|
export const Level = z.enum(['none', 'bronze', 'silver', 'gold']);
|
|
5
|
-
// Higher is better. The leaderboard sorts on it before the score.
|
|
5
|
+
// Higher is better. The leaderboard sorts on it before the score. Equal to
|
|
6
|
+
// the level's index on LADDER.
|
|
6
7
|
export const LEVEL_RANK = {
|
|
7
8
|
none: 0,
|
|
8
9
|
bronze: 1,
|
|
9
10
|
silver: 2,
|
|
10
11
|
gold: 3,
|
|
11
12
|
};
|
|
13
|
+
/*
|
|
14
|
+
* Every level of the standard, lowest first. issued levels are the ones a
|
|
15
|
+
* SEAL can carry. A reserved level is named and ordered but never issued,
|
|
16
|
+
* so no code may treat the highest issued level as the top of the ladder.
|
|
17
|
+
* Platinum is reserved. Level, LEVEL_RANK and the standing.level check
|
|
18
|
+
* constraint stay at the issued four, because the payload fields of a SEAL
|
|
19
|
+
* version are closed (standard, section 9) and published CLIs and offline
|
|
20
|
+
* verifiers reject a level they do not know. Platinum enters Level with a
|
|
21
|
+
* ver bump when it is issued.
|
|
22
|
+
*/
|
|
23
|
+
export const LADDER = [
|
|
24
|
+
{ level: 'none', state: 'issued' },
|
|
25
|
+
{ level: 'bronze', state: 'issued' },
|
|
26
|
+
{ level: 'silver', state: 'issued' },
|
|
27
|
+
{ level: 'gold', state: 'issued' },
|
|
28
|
+
{ level: 'platinum', state: 'reserved' },
|
|
29
|
+
];
|
|
30
|
+
// The issued levels of LADDER in order, the same values as Level.options.
|
|
31
|
+
export const ISSUED_LEVELS = LADDER.flatMap((step) => step.state === 'issued' ? [Level.parse(step.level)] : []);
|
|
12
32
|
const Count = z.int().min(0);
|
|
13
33
|
// The evidence counts of the SEAL standard, section 4, over the scoring
|
|
14
34
|
// window (180 days) for one agent version. The names are the standard's, so
|
|
@@ -79,10 +99,14 @@ export const COUNTED_EVIDENCE = {
|
|
|
79
99
|
};
|
|
80
100
|
export const DAY_MS = 86_400_000;
|
|
81
101
|
// The dormancy ladder of the SEAL standard, section 5, in whole days since
|
|
82
|
-
// the agent's last accepted event. At quietDays the
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
102
|
+
// the agent's last accepted event. At quietDays the level stays and the
|
|
103
|
+
// agent is quiet, which the agent answers carry (Standing.quiet, isQuiet)
|
|
104
|
+
// and the badge and profile show. At dropOneDays and dropTwoDays the level
|
|
105
|
+
// drops one step each. At noneDays the level is none and the scoring run
|
|
106
|
+
// stores no_seal, so the SEAL routes withhold the SEAL until a run after
|
|
107
|
+
// the agent is active again. An agent at none for any other reason still gets a SEAL
|
|
108
|
+
// that says none. The scoring job applies the ladder and the CLI explains
|
|
109
|
+
// it, so it lives here.
|
|
86
110
|
export const DORMANCY = {
|
|
87
111
|
quietDays: 14,
|
|
88
112
|
dropOneDays: 30,
|
|
@@ -92,12 +116,14 @@ export const DORMANCY = {
|
|
|
92
116
|
// SEAL standard levels, version 1 thresholds, section 5. Every one is a
|
|
93
117
|
// minimum and all of a level's must hold. The scoring job applies them
|
|
94
118
|
// (SCORING.levels in the API) and the CLI explains them, so they live here.
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
// (VOU-
|
|
99
|
-
//
|
|
100
|
-
//
|
|
119
|
+
// Task counts are counted evidence (CountedCounts), recalibrated on 26
|
|
120
|
+
// September 2026 (VOU-139) from the simulation in
|
|
121
|
+
// apps/api/src/scoring/simulation.ts. Seed tasks count in verifiedTasks at
|
|
122
|
+
// every level (VOU-172, 26 September 2026), so an agent that does seed
|
|
123
|
+
// tasks every day reaches silver on them alone. Silver dropped its
|
|
124
|
+
// checked or confirmed, other operator and confirmed task clauses then,
|
|
125
|
+
// and gold moved from 1000 verified and 250 confirmed from 25 operators to
|
|
126
|
+
// the step-ups below, with ratings left out until a later change.
|
|
101
127
|
export const LEVEL_THRESHOLDS = {
|
|
102
128
|
bronze: {
|
|
103
129
|
verifiedTasks: 25,
|
|
@@ -108,10 +134,6 @@ export const LEVEL_THRESHOLDS = {
|
|
|
108
134
|
},
|
|
109
135
|
silver: {
|
|
110
136
|
verifiedTasks: 200,
|
|
111
|
-
// Server checked plus confirmed tasks, from at least distinctOperators.
|
|
112
|
-
checkedOrConfirmed: 100,
|
|
113
|
-
distinctOperators: 5,
|
|
114
|
-
confirmedTasks: 25,
|
|
115
137
|
historyDays: 30,
|
|
116
138
|
reliability: 0.9,
|
|
117
139
|
safety: 0.9,
|
|
@@ -126,22 +148,37 @@ export const LEVEL_THRESHOLDS = {
|
|
|
126
148
|
modelDeclared: true,
|
|
127
149
|
},
|
|
128
150
|
gold: {
|
|
129
|
-
verifiedTasks:
|
|
130
|
-
// Confirmed tasks, from at least
|
|
131
|
-
|
|
132
|
-
|
|
151
|
+
verifiedTasks: 200,
|
|
152
|
+
// Confirmed tasks posted by hand with no routine report, from at least
|
|
153
|
+
// confirmedOperators other operators.
|
|
154
|
+
confirmedTasks: 25,
|
|
155
|
+
confirmedOperators: 3,
|
|
133
156
|
// Span from the first accepted event in the window, with activity on at
|
|
134
157
|
// least activeDays of those days.
|
|
135
158
|
historySpanDays: 90,
|
|
136
159
|
activeDays: 60,
|
|
137
160
|
reliability: 0.95,
|
|
138
161
|
safety: 0.95,
|
|
139
|
-
|
|
162
|
+
// Whole days since the later of the agent's first accepted event and
|
|
163
|
+
// its last incident, the clean_days count, which stops here.
|
|
164
|
+
cleanDays: 180,
|
|
140
165
|
operatorVerified: true,
|
|
141
|
-
// Ratings from silver or gold agents, net positive, at least this many.
|
|
142
|
-
ratings: 10,
|
|
143
166
|
},
|
|
144
167
|
};
|
|
168
|
+
// The operator silver cap (VOU-182, 26 September 2026). At most `agents`
|
|
169
|
+
// agents of one operator reach silver for the first time in any `days`
|
|
170
|
+
// days. The first time an agent earns silver it takes a grant, one of the
|
|
171
|
+
// operator's slots. An agent that finds no free slot is held at bronze
|
|
172
|
+
// until the oldest grant in the window is `days` days old. An agent keeps
|
|
173
|
+
// its grant through dormancy drops and version changes, and deleting it
|
|
174
|
+
// does not free the slot. Gold is above silver, so it needs the grant too.
|
|
175
|
+
// The scoring job applies it and the CLI explains it, so it lives here. A
|
|
176
|
+
// higher number for verified operators (20 proposed) is open. It would sit
|
|
177
|
+
// beside `agents` as its own key.
|
|
178
|
+
export const OPERATOR_SILVER_CAP = {
|
|
179
|
+
agents: 5,
|
|
180
|
+
days: 30,
|
|
181
|
+
};
|
|
145
182
|
// Whole days from lastActive to now, never below zero. null when the agent
|
|
146
183
|
// has sent no accepted event. The one place dormancy is counted.
|
|
147
184
|
export function dormantDays(lastActive, now) {
|
package/dist/tasks.d.ts
CHANGED
|
@@ -22,6 +22,28 @@ export declare const VerificationSpec: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
22
22
|
kind: z.ZodLiteral<"counterparty">;
|
|
23
23
|
}, z.core.$strict>], "kind">;
|
|
24
24
|
export type VerificationSpec = z.infer<typeof VerificationSpec>;
|
|
25
|
+
export declare const PublicHashVerification: z.ZodObject<{
|
|
26
|
+
kind: z.ZodLiteral<"hash">;
|
|
27
|
+
}, z.core.$strict>;
|
|
28
|
+
export declare const PublicVerificationSpec: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
29
|
+
kind: z.ZodLiteral<"hash">;
|
|
30
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
31
|
+
kind: z.ZodLiteral<"schema">;
|
|
32
|
+
jsonSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
33
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
34
|
+
kind: z.ZodLiteral<"counterparty">;
|
|
35
|
+
}, z.core.$strict>], "kind">;
|
|
36
|
+
export type PublicVerificationSpec = z.infer<typeof PublicVerificationSpec>;
|
|
37
|
+
export declare const ShownVerificationSpec: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
38
|
+
kind: z.ZodLiteral<"hash">;
|
|
39
|
+
sha256: z.ZodOptional<z.ZodString>;
|
|
40
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
41
|
+
kind: z.ZodLiteral<"schema">;
|
|
42
|
+
jsonSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
43
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
44
|
+
kind: z.ZodLiteral<"counterparty">;
|
|
45
|
+
}, z.core.$strict>], "kind">;
|
|
46
|
+
export type ShownVerificationSpec = z.infer<typeof ShownVerificationSpec>;
|
|
25
47
|
export declare const TaskOutcome: z.ZodEnum<{
|
|
26
48
|
failure: "failure";
|
|
27
49
|
success: "success";
|
|
@@ -45,5 +67,5 @@ export type TaskTimestamps = {
|
|
|
45
67
|
export declare function taskState(task: TaskTimestamps, now?: Date): TaskState;
|
|
46
68
|
type JsonObject = Record<string, unknown>;
|
|
47
69
|
export declare function redactJsonSchema(schema: JsonObject): JsonObject;
|
|
48
|
-
export declare function publicVerification(spec: VerificationSpec):
|
|
70
|
+
export declare function publicVerification(spec: VerificationSpec): PublicVerificationSpec;
|
|
49
71
|
export {};
|
package/dist/tasks.js
CHANGED
|
@@ -20,6 +20,26 @@ export const VerificationSpec = z.discriminatedUnion('kind', [
|
|
|
20
20
|
SchemaVerification,
|
|
21
21
|
CounterpartyVerification,
|
|
22
22
|
]);
|
|
23
|
+
// A hash task as everyone but its poster sees it, without the digest. With
|
|
24
|
+
// the digest in hand a claimant could hash candidate answers offline until
|
|
25
|
+
// one matched and submit only that one (VOU-181).
|
|
26
|
+
export const PublicHashVerification = z.strictObject({
|
|
27
|
+
kind: z.literal('hash'),
|
|
28
|
+
});
|
|
29
|
+
// The spec every public read shows, from publicVerification below.
|
|
30
|
+
export const PublicVerificationSpec = z.discriminatedUnion('kind', [
|
|
31
|
+
PublicHashVerification,
|
|
32
|
+
SchemaVerification,
|
|
33
|
+
CounterpartyVerification,
|
|
34
|
+
]);
|
|
35
|
+
// The spec a task response carries. The poster's own post and its signed
|
|
36
|
+
// submission read show the full spec, every other response the public one,
|
|
37
|
+
// so the digest is optional here and required in a post.
|
|
38
|
+
export const ShownVerificationSpec = z.discriminatedUnion('kind', [
|
|
39
|
+
z.strictObject({ kind: z.literal('hash'), sha256: Sha256Hex.optional() }),
|
|
40
|
+
SchemaVerification,
|
|
41
|
+
CounterpartyVerification,
|
|
42
|
+
]);
|
|
23
43
|
export const TaskOutcome = z.enum(['success', 'failure']);
|
|
24
44
|
export const TaskState = z.enum([
|
|
25
45
|
'open',
|
|
@@ -123,10 +143,14 @@ export function redactJsonSchema(schema) {
|
|
|
123
143
|
}
|
|
124
144
|
return out;
|
|
125
145
|
}
|
|
126
|
-
// What GET /v1/tasks and GET /v1/tasks/:id show.
|
|
127
|
-
//
|
|
146
|
+
// What GET /v1/tasks and GET /v1/tasks/:id show. A hash task drops its
|
|
147
|
+
// digest, which only the poster sees (VOU-181). A schema task shows its
|
|
148
|
+
// redacted schema. A counterparty spec has nothing to hide.
|
|
128
149
|
export function publicVerification(spec) {
|
|
129
|
-
if (spec.kind
|
|
130
|
-
return
|
|
131
|
-
|
|
150
|
+
if (spec.kind === 'hash')
|
|
151
|
+
return { kind: 'hash' };
|
|
152
|
+
if (spec.kind === 'schema') {
|
|
153
|
+
return { kind: 'schema', jsonSchema: redactJsonSchema(spec.jsonSchema) };
|
|
154
|
+
}
|
|
155
|
+
return spec;
|
|
132
156
|
}
|