@opum-ai/lore 0.1.0 → 0.2.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 (90) hide show
  1. package/README.md +33 -22
  2. package/bin/lore.cjs +35 -7
  3. package/package.json +17 -17
  4. package/src/adapters/backlog.ts +0 -1084
  5. package/src/adapters/git.ts +0 -221
  6. package/src/cli.ts +0 -667
  7. package/src/commands/agent.ts +0 -301
  8. package/src/commands/agents.ts +0 -302
  9. package/src/commands/args.ts +0 -209
  10. package/src/commands/changed.ts +0 -70
  11. package/src/commands/check.ts +0 -1031
  12. package/src/commands/codex-bridge.ts +0 -49
  13. package/src/commands/concurrency.ts +0 -48
  14. package/src/commands/context.ts +0 -292
  15. package/src/commands/discover.ts +0 -89
  16. package/src/commands/explorer.ts +0 -253
  17. package/src/commands/export.ts +0 -93
  18. package/src/commands/fswrite.ts +0 -928
  19. package/src/commands/graph.ts +0 -291
  20. package/src/commands/help.ts +0 -151
  21. package/src/commands/impact.ts +0 -59
  22. package/src/commands/init.ts +0 -583
  23. package/src/commands/instructions.ts +0 -91
  24. package/src/commands/link.ts +0 -929
  25. package/src/commands/new.ts +0 -476
  26. package/src/commands/orphans.ts +0 -457
  27. package/src/commands/path.ts +0 -67
  28. package/src/commands/provenance.ts +0 -68
  29. package/src/commands/query.ts +0 -312
  30. package/src/commands/reconcile-shared.ts +0 -280
  31. package/src/commands/rename.ts +0 -585
  32. package/src/commands/replace.ts +0 -320
  33. package/src/commands/scaffold.ts +0 -346
  34. package/src/commands/schema.ts +0 -293
  35. package/src/commands/snapshot.ts +0 -130
  36. package/src/commands/supersede.ts +0 -400
  37. package/src/commands/sync.ts +0 -371
  38. package/src/commands/tasks.ts +0 -271
  39. package/src/commands/traversal.ts +0 -151
  40. package/src/commands/validate.ts +0 -226
  41. package/src/config.ts +0 -598
  42. package/src/core/agent-bridge.ts +0 -287
  43. package/src/core/agent-context.ts +0 -498
  44. package/src/core/agent-profile.ts +0 -447
  45. package/src/core/bundle.ts +0 -893
  46. package/src/core/check.ts +0 -853
  47. package/src/core/codex-bridge.ts +0 -100
  48. package/src/core/concept.ts +0 -597
  49. package/src/core/consumer-scaffold.ts +0 -433
  50. package/src/core/context.ts +0 -271
  51. package/src/core/explorer-contract.ts +0 -441
  52. package/src/core/explorer-qualification.ts +0 -58
  53. package/src/core/explorer.ts +0 -518
  54. package/src/core/finding.ts +0 -31
  55. package/src/core/graph.ts +0 -201
  56. package/src/core/indexes.ts +0 -436
  57. package/src/core/instructions.ts +0 -209
  58. package/src/core/ladybug-driver.ts +0 -1795
  59. package/src/core/ladybug-lifecycle.ts +0 -1178
  60. package/src/core/ladybug-native.ts +0 -95
  61. package/src/core/ladybug-source.ts +0 -667
  62. package/src/core/links.ts +0 -681
  63. package/src/core/log.ts +0 -253
  64. package/src/core/managed-block.ts +0 -540
  65. package/src/core/manifest.ts +0 -718
  66. package/src/core/order.ts +0 -13
  67. package/src/core/profile.ts +0 -1007
  68. package/src/core/projection.ts +0 -195
  69. package/src/core/query.ts +0 -542
  70. package/src/core/reconcile.ts +0 -236
  71. package/src/core/replace.ts +0 -419
  72. package/src/core/retrieval.ts +0 -213
  73. package/src/core/rewrite.ts +0 -940
  74. package/src/core/scaffold.ts +0 -255
  75. package/src/core/schema.ts +0 -366
  76. package/src/core/snapshot-runtime.ts +0 -52
  77. package/src/core/snapshot-store.ts +0 -287
  78. package/src/core/snapshot.ts +0 -711
  79. package/src/core/template.ts +0 -429
  80. package/src/core/traversal.ts +0 -487
  81. package/src/core/validate.ts +0 -517
  82. package/src/core/workspace-contract.ts +0 -473
  83. package/src/core/workspace-projection.ts +0 -365
  84. package/src/core/workspace-retrieval.ts +0 -196
  85. package/src/core/workspace-source.ts +0 -174
  86. package/src/errors.ts +0 -697
  87. package/src/meta.ts +0 -7
  88. package/src/output.ts +0 -589
  89. package/src/scripts/upstream-backlog-watch.ts +0 -288
  90. package/src/state.ts +0 -390
@@ -1,441 +0,0 @@
1
- /**
2
- * Versioned, database-neutral read contract for the local graph explorer.
3
- *
4
- * The snapshot contains only source and derived health facts. Browser-local
5
- * layout coordinates and interaction state use the separate presentation
6
- * schema below and never participate in snapshot identity or serialization.
7
- */
8
-
9
- import { z } from "zod";
10
- import { compareCodeUnits } from "./order";
11
- import { type ChangedResult, compareRetainedSnapshots, parseRetainedSnapshot, type RetainedSnapshot } from "./snapshot";
12
-
13
- export const EXPLORER_SNAPSHOT_SCHEMA_VERSION = "lore-explorer-snapshot/1" as const;
14
- export const EXPLORER_CHANGE_SNAPSHOT_SCHEMA_VERSION = "lore-explorer-change-snapshot/1" as const;
15
- export const EXPLORER_PRESENTATION_SCHEMA_VERSION = "lore-explorer-presentation/1" as const;
16
-
17
- export const EXPLORER_RENDER_LIMITS = Object.freeze({
18
- initialNodeLimit: 750,
19
- initialEdgeLimit: 1_500,
20
- maximumVisibleNodes: 5_000,
21
- maximumVisibleEdges: 10_000,
22
- maximumFocusDepth: 4,
23
- });
24
-
25
- export const EXPLORER_REFRESH_CONTRACT = Object.freeze({
26
- hosts: Object.freeze(["127.0.0.1", "::1"] as const),
27
- method: "GET",
28
- responseSchemaVersion: EXPLORER_SNAPSHOT_SCHEMA_VERSION,
29
- canonicalSnapshotBytes: true,
30
- sameOriginOnly: true,
31
- acceptsQueryLanguage: false,
32
- acceptsDatabaseConfiguration: false,
33
- acceptsWrites: false,
34
- });
35
-
36
- export const EXPLORER_INTERACTION_CONTRACT = Object.freeze({
37
- keyboard: Object.freeze({
38
- id: "KBD-01",
39
- compositeNavigationKeys: Object.freeze(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"] as const),
40
- selectKey: "Enter",
41
- returnFocusKey: "Escape",
42
- pointerRequired: false,
43
- }),
44
- screenReader: Object.freeze({
45
- id: "SR-01",
46
- equivalentListRequired: true,
47
- liveRegionPoliteness: "polite",
48
- canvasOnlyTextAllowed: false,
49
- }),
50
- color: Object.freeze({
51
- id: "COLOR-01",
52
- minimumContrast: "WCAG 2.2 AA",
53
- redundantNonColorCueRequired: true,
54
- }),
55
- responsive: Object.freeze({
56
- id: "RESPONSIVE-01",
57
- minimumViewportCssPixels: 320,
58
- zoomPercent: 200,
59
- twoDimensionalPageScrollAllowed: false,
60
- }),
61
- empty: Object.freeze({
62
- id: "EMPTY-01",
63
- healthState: "empty",
64
- initialFocus: "status-heading",
65
- navigationEnabled: false,
66
- }),
67
- corrupt: Object.freeze({
68
- id: "CORRUPT-01",
69
- healthState: "corrupt",
70
- navigationEnabled: false,
71
- destructiveActionAllowed: false,
72
- }),
73
- stale: Object.freeze({
74
- id: "STALE-01",
75
- healthState: "stale",
76
- preservesLastCompleteViewOnRefreshFailure: true,
77
- displayedProvenanceRequired: true,
78
- }),
79
- largeGraph: Object.freeze({
80
- id: "SCALE-01",
81
- announcesTotalAndVisibleCounts: true,
82
- requiresExplicitExpansion: true,
83
- limits: EXPLORER_RENDER_LIMITS,
84
- }),
85
- });
86
-
87
- const digestSchema = z.string().regex(/^sha256:[0-9a-f]{64}$/u);
88
- const commitSchema = z
89
- .string()
90
- .regex(/^[0-9a-f]{40}$/u)
91
- .nullable();
92
- const sourcePathSchema = z
93
- .string()
94
- .min(1)
95
- .refine(
96
- (path) =>
97
- !path.startsWith("/") &&
98
- !path.includes("\\") &&
99
- path.split("/").every((segment) => segment !== "" && segment !== "." && segment !== ".."),
100
- {
101
- message: "source paths must be repository-relative POSIX paths",
102
- },
103
- );
104
-
105
- const sourceIdentitySchema = z
106
- .object({
107
- repositoryScopeKey: digestSchema,
108
- snapshotKey: digestSchema,
109
- bundleId: digestSchema,
110
- gitCommit: commitSchema,
111
- exportDigest: digestSchema,
112
- })
113
- .strict();
114
-
115
- const recordProvenanceSchema = sourceIdentitySchema
116
- .extend({
117
- recordKey: digestSchema,
118
- sourcePath: sourcePathSchema.nullable(),
119
- })
120
- .strict();
121
-
122
- const repositoryFactSchema = sourceIdentitySchema
123
- .extend({
124
- kind: z.literal("repository"),
125
- docsRoot: sourcePathSchema,
126
- displayName: z.string().min(1).max(256),
127
- })
128
- .strict();
129
-
130
- const conceptFactSchema = recordProvenanceSchema
131
- .extend({
132
- kind: z.literal("concept"),
133
- conceptId: z.string().min(1),
134
- conceptType: z.string().min(1),
135
- title: z.string().max(1_024).nullable(),
136
- summary: z.string().max(4_096).nullable(),
137
- status: z.string().max(256).nullable(),
138
- tags: z.array(z.string().max(256)).max(256),
139
- contentHash: digestSchema,
140
- tokenEstimate: z.number().int().nonnegative(),
141
- })
142
- .strict();
143
-
144
- const taskFactSchema = recordProvenanceSchema
145
- .extend({
146
- kind: z.literal("task"),
147
- taskId: z.string().min(1),
148
- title: z.string().min(1).max(1_024),
149
- summary: z.string().max(4_096).nullable(),
150
- status: z.string().min(1).max(256),
151
- labels: z.array(z.string().max(256)).max(256),
152
- priority: z.string().max(256).nullable(),
153
- assignees: z.array(z.string().max(256)).max(256),
154
- milestone: z.string().max(256).nullable(),
155
- parentTaskId: z.string().max(256).nullable(),
156
- })
157
- .strict();
158
-
159
- const authoredEdgeFactSchema = recordProvenanceSchema
160
- .extend({
161
- kind: z.literal("authored-edge"),
162
- edgeKind: z.string().min(1).max(256),
163
- fromRecordKey: digestSchema,
164
- toRecordKey: digestSchema.nullable(),
165
- target: z.string().min(1),
166
- ordinal: z.number().int().nonnegative(),
167
- dangling: z.boolean(),
168
- })
169
- .strict();
170
-
171
- const graphCountsSchema = z
172
- .object({
173
- repositories: z.number().int().nonnegative(),
174
- concepts: z.number().int().nonnegative(),
175
- tasks: z.number().int().nonnegative(),
176
- authoredEdges: z.number().int().nonnegative(),
177
- danglingEdges: z.number().int().nonnegative(),
178
- duplicateEdges: z.number().int().nonnegative(),
179
- })
180
- .strict();
181
-
182
- export const explorerSnapshotSchema = z
183
- .object({
184
- schemaVersion: z.literal(EXPLORER_SNAPSHOT_SCHEMA_VERSION),
185
- source: sourceIdentitySchema.extend({
186
- docsRoot: sourcePathSchema,
187
- sourceFingerprint: digestSchema,
188
- generatedAt: z.null(),
189
- }),
190
- facts: z
191
- .object({
192
- repositories: z.array(repositoryFactSchema),
193
- concepts: z.array(conceptFactSchema),
194
- tasks: z.array(taskFactSchema),
195
- authoredEdges: z.array(authoredEdgeFactSchema),
196
- })
197
- .strict(),
198
- health: z
199
- .object({
200
- state: z.enum(["ready", "empty", "stale", "corrupt"]),
201
- messageCode: z.string().max(256).nullable(),
202
- counts: graphCountsSchema,
203
- warnings: z.array(z.string().max(1_024)).max(64),
204
- })
205
- .strict(),
206
- })
207
- .strict();
208
-
209
- export const explorerPresentationStateSchema = z
210
- .object({
211
- schemaVersion: z.literal(EXPLORER_PRESENTATION_SCHEMA_VERSION),
212
- snapshotKey: digestSchema,
213
- filters: z
214
- .object({
215
- search: z.string().max(256),
216
- kinds: z.array(z.enum(["repository", "concept", "task"])),
217
- statuses: z.array(z.string().max(256)),
218
- edgeKinds: z.array(z.string().max(256)),
219
- graphHealth: z.array(z.enum(["dangling", "duplicate", "supersession"])),
220
- })
221
- .strict(),
222
- selection: z
223
- .object({
224
- selectedRecordKey: digestSchema.nullable(),
225
- focusRecordKey: digestSchema.nullable(),
226
- depth: z.number().int().min(0).max(EXPLORER_RENDER_LIMITS.maximumFocusDepth),
227
- })
228
- .strict(),
229
- layout: z
230
- .object({
231
- algorithmVersion: z.string().min(1).max(256),
232
- coordinates: z
233
- .array(
234
- z
235
- .object({
236
- recordKey: digestSchema,
237
- x: z.number().finite(),
238
- y: z.number().finite(),
239
- })
240
- .strict(),
241
- )
242
- .max(EXPLORER_RENDER_LIMITS.maximumVisibleNodes),
243
- viewport: z
244
- .object({
245
- x: z.number().finite(),
246
- y: z.number().finite(),
247
- zoom: z.number().finite().positive(),
248
- })
249
- .strict(),
250
- })
251
- .strict(),
252
- })
253
- .strict();
254
-
255
- export type ExplorerSnapshot = z.infer<typeof explorerSnapshotSchema>;
256
- export type ExplorerPresentationState = z.infer<typeof explorerPresentationStateSchema>;
257
-
258
- /** Retained facts plus a reproducible bounded delta for offline historical exploration. */
259
- export interface ExplorerChangeSnapshot {
260
- readonly schemaVersion: typeof EXPLORER_CHANGE_SNAPSHOT_SCHEMA_VERSION;
261
- readonly mode: "snapshot" | "comparison";
262
- readonly from: RetainedSnapshot;
263
- readonly to: RetainedSnapshot;
264
- readonly comparison: ChangedResult;
265
- }
266
-
267
- const explorerChangeEnvelopeSchema = z
268
- .object({
269
- schemaVersion: z.literal(EXPLORER_CHANGE_SNAPSHOT_SCHEMA_VERSION),
270
- mode: z.enum(["snapshot", "comparison"]),
271
- from: z.unknown(),
272
- to: z.unknown(),
273
- comparison: z.unknown(),
274
- })
275
- .strict();
276
-
277
- const changedReplaySchema = z
278
- .object({
279
- filters: z
280
- .object({
281
- repositories: z.array(z.string()),
282
- kinds: z.array(z.enum(["concept", "task", "edge"])),
283
- })
284
- .strict(),
285
- limits: z.object({ result: z.number().int(), factScan: z.number().int() }).strict(),
286
- })
287
- .passthrough();
288
-
289
- /** Parse historical explorer input and prove its delta is reproducible from embedded source facts. */
290
- export function parseExplorerChangeSnapshot(value: unknown): ExplorerChangeSnapshot {
291
- const envelope = explorerChangeEnvelopeSchema.parse(value);
292
- const from = parseRetainedSnapshot(envelope.from);
293
- const to = parseRetainedSnapshot(envelope.to);
294
- const replay = changedReplaySchema.parse(envelope.comparison);
295
- const comparison = compareRetainedSnapshots(from, to, {
296
- limit: replay.limits.result,
297
- repositories: replay.filters.repositories,
298
- kinds: replay.filters.kinds,
299
- });
300
- if (canonicalJson(envelope.comparison) !== canonicalJson(comparison)) {
301
- throw new Error(
302
- `invalid ${EXPLORER_CHANGE_SNAPSHOT_SCHEMA_VERSION}: comparison does not match embedded retained facts`,
303
- );
304
- }
305
- if (envelope.mode === "snapshot" && canonicalJson(from) !== canonicalJson(to)) {
306
- throw new Error(
307
- `invalid ${EXPLORER_CHANGE_SNAPSHOT_SCHEMA_VERSION}: snapshot mode requires one identical snapshot`,
308
- );
309
- }
310
- return { schemaVersion: envelope.schemaVersion, mode: envelope.mode, from, to, comparison };
311
- }
312
-
313
- export function serializeExplorerChangeSnapshot(value: unknown): string {
314
- return `${canonicalJson(parseExplorerChangeSnapshot(value))}\n`;
315
- }
316
-
317
- /** Parse the public snapshot and enforce cross-record determinism/provenance invariants. */
318
- export function parseExplorerSnapshot(value: unknown): ExplorerSnapshot {
319
- const snapshot = explorerSnapshotSchema.parse(value);
320
- assertSortedUnique(snapshot.facts.repositories, (record) => record.repositoryScopeKey, "repositories");
321
- assertSortedUnique(snapshot.facts.concepts, (record) => record.recordKey, "concepts");
322
- assertSortedUnique(snapshot.facts.tasks, (record) => record.recordKey, "tasks");
323
- assertSortedUnique(snapshot.health.warnings, (warning) => warning, "warnings");
324
- assertEdgesSortedUnique(snapshot.facts.authoredEdges);
325
-
326
- const sourceIdentity = identityTuple(snapshot.source);
327
- const recordKeys = new Set<string>();
328
- for (const repository of snapshot.facts.repositories) {
329
- assertIdentity(repository, sourceIdentity, "repository");
330
- }
331
- for (const record of [...snapshot.facts.concepts, ...snapshot.facts.tasks]) {
332
- assertIdentity(record, sourceIdentity, record.kind);
333
- if (recordKeys.has(record.recordKey)) throw contractError(`duplicate record key ${record.recordKey}`);
334
- recordKeys.add(record.recordKey);
335
- }
336
- const nodeKeys = new Set(recordKeys);
337
-
338
- const edgeFingerprints = new Set<string>();
339
- let duplicateEdges = 0;
340
- let danglingEdges = 0;
341
- for (const edge of snapshot.facts.authoredEdges) {
342
- assertIdentity(edge, sourceIdentity, "authored edge");
343
- if (recordKeys.has(edge.recordKey)) throw contractError(`duplicate record key ${edge.recordKey}`);
344
- recordKeys.add(edge.recordKey);
345
- if (!nodeKeys.has(edge.fromRecordKey)) throw contractError(`missing edge source ${edge.fromRecordKey}`);
346
- if (edge.dangling !== (edge.toRecordKey === null)) {
347
- throw contractError(`edge ${edge.recordKey} has inconsistent dangling state`);
348
- }
349
- if (edge.toRecordKey !== null && !nodeKeys.has(edge.toRecordKey)) {
350
- throw contractError(`missing edge target ${edge.toRecordKey}`);
351
- }
352
- if (edge.dangling) danglingEdges++;
353
- const fingerprint = [edge.fromRecordKey, edge.edgeKind, edge.target].join("\0");
354
- if (edgeFingerprints.has(fingerprint)) duplicateEdges++;
355
- edgeFingerprints.add(fingerprint);
356
- }
357
-
358
- const actualCounts = {
359
- repositories: snapshot.facts.repositories.length,
360
- concepts: snapshot.facts.concepts.length,
361
- tasks: snapshot.facts.tasks.length,
362
- authoredEdges: snapshot.facts.authoredEdges.length,
363
- danglingEdges,
364
- duplicateEdges,
365
- };
366
- if (canonicalJson(snapshot.health.counts) !== canonicalJson(actualCounts)) {
367
- throw contractError("graph-health counts do not match source facts");
368
- }
369
- const factCount = actualCounts.repositories + actualCounts.concepts + actualCounts.tasks + actualCounts.authoredEdges;
370
- if (snapshot.health.state === "empty" && factCount !== 0) {
371
- throw contractError("empty graph-health state cannot carry source facts");
372
- }
373
- if (snapshot.health.state !== "empty" && actualCounts.repositories !== 1) {
374
- throw contractError(`${snapshot.health.state} graph-health state requires exactly one M6 repository`);
375
- }
376
- if (
377
- (snapshot.health.state === "stale" || snapshot.health.state === "corrupt") &&
378
- snapshot.health.messageCode === null
379
- ) {
380
- throw contractError(`${snapshot.health.state} graph-health state requires a stable message code`);
381
- }
382
- return snapshot;
383
- }
384
-
385
- /** Serialize one validated snapshot as canonical UTF-8 JSON with a trailing newline. */
386
- export function serializeExplorerSnapshot(value: unknown): string {
387
- return `${canonicalJson(parseExplorerSnapshot(value))}\n`;
388
- }
389
-
390
- function identityTuple(identity: z.infer<typeof sourceIdentitySchema>): string {
391
- return [
392
- identity.repositoryScopeKey,
393
- identity.snapshotKey,
394
- identity.bundleId,
395
- identity.gitCommit ?? "",
396
- identity.exportDigest,
397
- ].join("\0");
398
- }
399
-
400
- function assertIdentity(identity: z.infer<typeof sourceIdentitySchema>, expected: string, label: string): void {
401
- if (identityTuple(identity) !== expected) throw contractError(`${label} provenance differs from snapshot source`);
402
- }
403
-
404
- function assertSortedUnique<T>(records: readonly T[], key: (record: T) => string, label: string): void {
405
- for (let index = 1; index < records.length; index++) {
406
- const previous = records[index - 1];
407
- const current = records[index];
408
- if (previous === undefined || current === undefined) continue;
409
- if (compareCodeUnits(key(previous), key(current)) >= 0) {
410
- throw contractError(`${label} must be unique and sorted by UTF-16 code units`);
411
- }
412
- }
413
- }
414
-
415
- function assertEdgesSortedUnique(edges: readonly z.infer<typeof authoredEdgeFactSchema>[]): void {
416
- const key = (edge: z.infer<typeof authoredEdgeFactSchema>) =>
417
- [edge.fromRecordKey, edge.edgeKind, edge.target, String(edge.ordinal).padStart(16, "0"), edge.recordKey].join("\0");
418
- assertSortedUnique(edges, key, "authored edges");
419
- }
420
-
421
- function contractError(message: string): Error {
422
- return new Error(`invalid ${EXPLORER_SNAPSHOT_SCHEMA_VERSION}: ${message}`);
423
- }
424
-
425
- /** RFC-8259-compatible deterministic JSON with lexicographically sorted object keys. */
426
- function canonicalJson(value: unknown): string {
427
- return JSON.stringify(canonicalValue(value));
428
- }
429
-
430
- function canonicalValue(value: unknown): unknown {
431
- if (Array.isArray(value)) return value.map((entry) => canonicalValue(entry));
432
- if (value === null || typeof value !== "object") return value;
433
- const result: Record<string, unknown> = {};
434
- for (const key of Object.keys(value).sort(compareCodeUnits)) {
435
- const entry = (value as Record<string, unknown>)[key];
436
- if (entry !== undefined && typeof entry !== "function" && typeof entry !== "symbol") {
437
- result[key] = canonicalValue(entry);
438
- }
439
- }
440
- return result;
441
- }
@@ -1,58 +0,0 @@
1
- /** Frozen browser and scale qualification for the static graph explorer. */
2
-
3
- export const EXPLORER_QUALIFICATION_SCHEMA_VERSION = "lore-explorer-qualification/1" as const;
4
-
5
- export const EXPLORER_SUPPORTED_BROWSERS = Object.freeze(["chromium", "firefox", "webkit"] as const);
6
-
7
- export const EXPLORER_LARGE_FIXTURE = Object.freeze({
8
- seed: "lore-explorer-large-v1",
9
- concepts: 5_000,
10
- tasks: 1_000,
11
- authoredEdges: 10_000,
12
- });
13
-
14
- export const EXPLORER_QUALIFICATION_BUDGETS = Object.freeze({
15
- artifactBytes: 32 * 1024 * 1024,
16
- loadMilliseconds: 15_000,
17
- interactionMilliseconds: 2_500,
18
- mountedElements: 7_500,
19
- heapBytes: 512 * 1024 * 1024,
20
- });
21
-
22
- export interface ExplorerQualificationFixture {
23
- readonly schemaVersion: typeof EXPLORER_QUALIFICATION_SCHEMA_VERSION;
24
- readonly playwrightVersion: "1.62.1";
25
- readonly browsers: typeof EXPLORER_SUPPORTED_BROWSERS;
26
- readonly seed: typeof EXPLORER_LARGE_FIXTURE.seed;
27
- readonly records: {
28
- readonly concepts: typeof EXPLORER_LARGE_FIXTURE.concepts;
29
- readonly tasks: typeof EXPLORER_LARGE_FIXTURE.tasks;
30
- readonly authoredEdges: typeof EXPLORER_LARGE_FIXTURE.authoredEdges;
31
- };
32
- readonly budgets: {
33
- readonly artifactBytes: number;
34
- readonly loadMilliseconds: number;
35
- readonly interactionMilliseconds: number;
36
- readonly mountedElements: number;
37
- readonly heapBytes: number;
38
- };
39
- }
40
-
41
- export function assertExplorerQualificationFixture(value: unknown): ExplorerQualificationFixture {
42
- const expected: ExplorerQualificationFixture = {
43
- schemaVersion: EXPLORER_QUALIFICATION_SCHEMA_VERSION,
44
- playwrightVersion: "1.62.1",
45
- browsers: EXPLORER_SUPPORTED_BROWSERS,
46
- seed: EXPLORER_LARGE_FIXTURE.seed,
47
- records: {
48
- concepts: EXPLORER_LARGE_FIXTURE.concepts,
49
- tasks: EXPLORER_LARGE_FIXTURE.tasks,
50
- authoredEdges: EXPLORER_LARGE_FIXTURE.authoredEdges,
51
- },
52
- budgets: EXPLORER_QUALIFICATION_BUDGETS,
53
- };
54
- if (JSON.stringify(value) !== JSON.stringify(expected)) {
55
- throw new Error(`explorer qualification fixture must match ${EXPLORER_QUALIFICATION_SCHEMA_VERSION}`);
56
- }
57
- return expected;
58
- }