keepset 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,7 +63,7 @@ The catalogue itself is a manifest (`catalogue/manifest.json`: id, version, repo
63
63
 
64
64
  ## Categories and normalisation targets
65
65
 
66
- A category names a normalisation target: the shape every entry in that category resolves to, whatever its native shape. `graph/v1` is `{ meta, nodes, edges }` with unique node ids and edges whose endpoints name nodes; its entries are graph datasets taken from upstream collections such as SuiteSparse, Netzschleuder, SNAP, KONECT and OGB. `or/v1` is `{ meta, nodes }`, an operations-research instance as the nodes it offers to visit, each flat with optional coordinates, prize, prize probability, duration, travel time, skill, territory, lifecycle status and times, and deadline, read from tabular sources by the `csv-table` parser (a delimited file, a member of an archive, a sheet of an Excel workbook, or an open data portal read a page at a time) and from ArcGIS feature layers by the `geojson` parser. Its entries come from a survey of open operations-research datasets, imported with a curation that records, for each source, what its download gives and how its columns map onto the node; a dataset whose source has no usable table is imported without a recipe and says why. `or-set/v1` is `{ meta, instances }`, a collection of operations-research instances such as a benchmark suite, each instance an `or/v1` document under an id of its own (for a collection read from an archive, the path of the member it came from): a recipe selects every matching archive member with `members`, the parser reads each one, and a member that does not parse fails the fetch and is named. A new category starts by defining its target schema in `src/targets/` and registering it in the category registry; an entry cannot name a category that does not exist. The statically generated site renders every entry with schema.org Dataset JSON-LD, so the catalogue surfaces in the dataset discovery layers.
66
+ A category names a normalisation target: the shape every entry in that category resolves to, whatever its native shape. `graph/v1` is `{ meta, nodes, edges }` with unique node ids and edges whose endpoints name nodes; its entries are graph datasets taken from upstream collections such as SuiteSparse, Netzschleuder, SNAP, KONECT and OGB. `or/v1` is `{ meta, nodes }`, an operations-research instance as the nodes it offers to visit, each flat with optional coordinates, prize, prize probability, duration, travel time, skill, territory, lifecycle status and times, and deadline, read from tabular sources by the `csv-table` parser (a delimited file, a member of an archive, a sheet of an Excel workbook, or an open data portal read a page at a time) and from ArcGIS feature layers by the `geojson` parser. Its entries come from a survey of open operations-research datasets, imported with a curation that records, for each source, what its download gives and how its columns map onto the node; a dataset whose source has no usable table is imported without a recipe and says why. `or-set/v1` is `{ meta, instances }`, a collection of operations-research instances such as a benchmark suite, each instance an `or/v1` document under an id of its own (for a collection read from an archive, the path of the member it came from): a recipe selects every matching archive member with `members` (by path, by the extensions its name ends with, or by a regular expression its whole path matches), the parser reads each one, and a member that does not parse fails the fetch and is named. Instance files are read by one parser per format (Solomon and TOPTW time window files, Chao team orienteering files, TSPLIB style orienteering files, VRP-REP XML, VeRoLog 2019 files and customer point lists), which gives each node the columns the file has and each instance a header of its own; a curation says which of them fill the `or/v1` node's fields, which pass through under their own names and which are dropped, so what an entry leaves out is written down, and a source whose time quantities are not seconds keeps them under the source's names with the unit recorded as the entry's `timeUnit`. A new category starts by defining its target schema in `src/targets/` and registering it in the category registry; an entry cannot name a category that does not exist. The statically generated site renders every entry with schema.org Dataset JSON-LD, so the catalogue surfaces in the dataset discovery layers.
67
67
 
68
68
  ## Licensing
69
69
 
@@ -453,8 +453,21 @@ const CitationSchema = z.object({
453
453
  }).strict();
454
454
  /** A relative path inside an archive or a catalogue: `/`-separated segments, none empty, `.` or `..`, so it can never climb out of the directory it is resolved against. */
455
455
  const RelativePathSchema = z.string().refine((path) => path.split("/").every((segment) => segment !== "" && segment !== "." && segment !== ".."), { message: "must be a relative path of non-empty segments with no '.' or '..'" });
456
- /** Which file of an archive to read: a member path, matched against a member's whole path or its trailing segments (so `net.gml` finds `net/net.gml`), or the member whose name ends with one of a list of extensions (a format can have several, such as Pajek's `.net` and `.paj`). Either must match exactly one member when the recipe runs; macOS resource-fork members (`__MACOSX/` and `._` files) never match. */
457
- const ArchiveMemberSchema = z.union([z.object({ path: RelativePathSchema }).strict(), z.object({ extensions: z.array(z.string().regex(/^\.[A-Za-z0-9][A-Za-z0-9.]*$/, { message: "must be a file extension such as .mtx" })).min(1) }).strict()]);
456
+ /** A regular expression a member path must match in full, in JavaScript syntax; it must compile, so a recipe with a malformed pattern is refused when the entry is parsed and not when it runs. */
457
+ const MemberPatternSchema = z.string().min(1).refine((pattern) => {
458
+ try {
459
+ new RegExp(`^(?:${pattern})$`, "u");
460
+ return true;
461
+ } catch {
462
+ return false;
463
+ }
464
+ }, { message: "must be a valid regular expression" });
465
+ /** Which file of an archive to read: a member path, matched against a member's whole path or its trailing segments (so `net.gml` finds `net/net.gml`), the member whose name ends with one of a list of extensions (a format can have several, such as Pajek's `.net` and `.paj`), or the member whose whole path matches a regular expression (for an archive whose instance files cannot be told from its readmes and solutions by extension). A `member` selector must match exactly one member when the recipe runs, a `members` selector at least one; macOS resource-fork members (`__MACOSX/` and `._` files) never match. */
466
+ const ArchiveMemberSchema = z.union([
467
+ z.object({ path: RelativePathSchema }).strict(),
468
+ z.object({ extensions: z.array(z.string().regex(/^\.[A-Za-z0-9][A-Za-z0-9.]*$/, { message: "must be a file extension such as .mtx" })).min(1) }).strict(),
469
+ z.object({ pattern: MemberPatternSchema }).strict()
470
+ ]);
458
471
  /** The archive kinds that hold several files, from which a recipe selects one (`member`) or every one a selector matches (`members`). */
459
472
  const FileArchiveKindSchema = z.enum([
460
473
  "zip",
@@ -517,6 +530,10 @@ const ParserSchema = z.discriminatedUnion("format", [
517
530
  format: z.literal("pajek"),
518
531
  encoding: EncodingSchema
519
532
  }).strict(),
533
+ z.object({
534
+ format: z.literal("customer-points"),
535
+ encoding: EncodingSchema
536
+ }).strict(),
520
537
  z.object({
521
538
  format: z.literal("solomon"),
522
539
  encoding: EncodingSchema
@@ -533,6 +550,14 @@ const ParserSchema = z.discriminatedUnion("format", [
533
550
  format: z.literal("tsplib"),
534
551
  encoding: EncodingSchema
535
552
  }).strict(),
553
+ z.object({
554
+ format: z.literal("verolog-2019"),
555
+ encoding: z.literal("utf-8")
556
+ }).strict(),
557
+ z.object({
558
+ format: z.literal("vrp-rep"),
559
+ encoding: z.literal("utf-8")
560
+ }).strict(),
536
561
  z.object({
537
562
  format: z.literal("csv-table"),
538
563
  encoding: EncodingSchema,
@@ -992,7 +1017,7 @@ var catalogue_default = {
992
1017
  "id": "keepset",
993
1018
  "name": "keepset",
994
1019
  "description": "The keepset catalogue: datasets with machine-readable recipes that fetch each one and normalise it into its category's target shape.",
995
- "version": "1.14.0",
1020
+ "version": "1.17.0",
996
1021
  "repository": "https://github.com/Mearman/keepset",
997
1022
  "namespaceAliases": {
998
1023
  "networkrepository": ["nr"],
@@ -7081,7 +7106,7 @@ var catalogue_default = {
7081
7106
  "citations": [],
7082
7107
  "recipe": {
7083
7108
  "status": "not-fetchable",
7084
- "reason": "The instances are keyword format text files of matrices (a collection of many, indexed by dataset.csv), and a collection is more than one or/v1 document, so no recipe reads it."
7109
+ "reason": "The instances are keyword format text files with node positions, time windows, service durations and a travel time matrix, but the repository holds them as a very large number of separate files in size directories and publishes no archive of the curated selection, so a recipe has no single download to read; the repository's own archive holds every instance and is several gigabytes."
7085
7110
  },
7086
7111
  "crosswalk": { "file": "crosswalks/or-v1/nodes.json" },
7087
7112
  "expectedCounts": {},
@@ -7099,20 +7124,153 @@ var catalogue_default = {
7099
7124
  "skills",
7100
7125
  "travelTime"
7101
7126
  ],
7102
- "category": "or/v1",
7127
+ "category": "or-set/v1",
7103
7128
  "sources": [{
7104
7129
  "url": "https://github.com/BasCoding/VeRoLog-2019",
7105
7130
  "retrieved": "2026-10-19",
7106
7131
  "status": "live"
7132
+ }, {
7133
+ "url": "https://codeload.github.com/BasCoding/VeRoLog-2019/zip/refs/heads/main",
7134
+ "retrieved": "2026-10-19",
7135
+ "status": "live"
7107
7136
  }],
7108
7137
  "licence": { "kind": "unrecorded" },
7109
7138
  "citations": [],
7110
7139
  "recipe": {
7111
- "status": "not-fetchable",
7112
- "reason": "The instances are keyword format text files in a collection mirrored by a student without a licence statement, and a collection is more than one or/v1 document, so no recipe reads it."
7140
+ "status": "fetchable",
7141
+ "source": 1,
7142
+ "archive": {
7143
+ "kind": "zip",
7144
+ "members": { "pattern": "VeRoLog-2019-main/All Instances/VSC2019_(?:EX\\d\\d|ORTEC_early_\\d\\d)\\.txt" }
7145
+ },
7146
+ "parser": {
7147
+ "format": "verolog-2019",
7148
+ "encoding": "utf-8"
7149
+ }
7113
7150
  },
7114
- "crosswalk": { "file": "crosswalks/or-v1/nodes.json" },
7115
- "expectedCounts": {},
7151
+ "crosswalk": {
7152
+ "source": "verolog-2019",
7153
+ "target": "or-set/v1",
7154
+ "rules": [
7155
+ {
7156
+ "op": "move",
7157
+ "from": "meta",
7158
+ "to": "meta"
7159
+ },
7160
+ {
7161
+ "op": "move",
7162
+ "from": "members[].id",
7163
+ "to": "instances[].id"
7164
+ },
7165
+ {
7166
+ "op": "move",
7167
+ "from": "members[].meta.dataset",
7168
+ "to": "instances[].meta.dataset"
7169
+ },
7170
+ {
7171
+ "op": "move",
7172
+ "from": "members[].meta.name",
7173
+ "to": "instances[].meta.name"
7174
+ },
7175
+ {
7176
+ "op": "move",
7177
+ "from": "members[].meta.days",
7178
+ "to": "instances[].meta.days"
7179
+ },
7180
+ {
7181
+ "op": "move",
7182
+ "from": "members[].meta.truckCapacity",
7183
+ "to": "instances[].meta.truckCapacity"
7184
+ },
7185
+ {
7186
+ "op": "move",
7187
+ "from": "members[].meta.truckMaxDistance",
7188
+ "to": "instances[].meta.truckMaxDistance"
7189
+ },
7190
+ {
7191
+ "op": "move",
7192
+ "from": "members[].meta.truckDistanceCost",
7193
+ "to": "instances[].meta.truckDistanceCost"
7194
+ },
7195
+ {
7196
+ "op": "move",
7197
+ "from": "members[].meta.truckDayCost",
7198
+ "to": "instances[].meta.truckDayCost"
7199
+ },
7200
+ {
7201
+ "op": "move",
7202
+ "from": "members[].meta.truckCost",
7203
+ "to": "instances[].meta.truckCost"
7204
+ },
7205
+ {
7206
+ "op": "move",
7207
+ "from": "members[].meta.technicianDistanceCost",
7208
+ "to": "instances[].meta.technicianDistanceCost"
7209
+ },
7210
+ {
7211
+ "op": "move",
7212
+ "from": "members[].meta.technicianDayCost",
7213
+ "to": "instances[].meta.technicianDayCost"
7214
+ },
7215
+ {
7216
+ "op": "move",
7217
+ "from": "members[].meta.technicianCost",
7218
+ "to": "instances[].meta.technicianCost"
7219
+ },
7220
+ {
7221
+ "op": "move",
7222
+ "from": "members[].meta.technicians",
7223
+ "to": "instances[].meta.technicians"
7224
+ },
7225
+ {
7226
+ "op": "move",
7227
+ "from": "members[].nodes[].id",
7228
+ "to": "instances[].nodes[].id"
7229
+ },
7230
+ {
7231
+ "op": "move",
7232
+ "from": "members[].nodes[].machine",
7233
+ "to": "instances[].nodes[].skill"
7234
+ },
7235
+ {
7236
+ "op": "move",
7237
+ "from": "members[].nodes[].x",
7238
+ "to": "instances[].nodes[].x"
7239
+ },
7240
+ {
7241
+ "op": "move",
7242
+ "from": "members[].nodes[].y",
7243
+ "to": "instances[].nodes[].y"
7244
+ },
7245
+ {
7246
+ "op": "move",
7247
+ "from": "members[].nodes[].kind",
7248
+ "to": "instances[].nodes[].kind"
7249
+ },
7250
+ {
7251
+ "op": "move",
7252
+ "from": "members[].nodes[].location",
7253
+ "to": "instances[].nodes[].location"
7254
+ },
7255
+ {
7256
+ "op": "move",
7257
+ "from": "members[].nodes[].fromDay",
7258
+ "to": "instances[].nodes[].fromDay"
7259
+ },
7260
+ {
7261
+ "op": "move",
7262
+ "from": "members[].nodes[].toDay",
7263
+ "to": "instances[].nodes[].toDay"
7264
+ },
7265
+ {
7266
+ "op": "move",
7267
+ "from": "members[].nodes[].amount",
7268
+ "to": "instances[].nodes[].amount"
7269
+ }
7270
+ ],
7271
+ "oneWay": []
7272
+ },
7273
+ "expectedCounts": { "instances": 27 },
7116
7274
  "properties": { "surveyId": "or-24" }
7117
7275
  },
7118
7276
  {
@@ -17178,7 +17336,7 @@ var catalogue_default = {
17178
17336
  "citations": [],
17179
17337
  "recipe": {
17180
17338
  "status": "not-fetchable",
17181
- "reason": "The instances are keyword format text files on a Wayback Machine snapshot, a collection of separate files, and a collection is more than one or/v1 document, so no recipe reads it."
17339
+ "reason": "The instances are keyword format text files that the Wayback Machine serves one at a time, as the archive zips of each set were not captured, and a recipe reads one download, so no recipe reaches the collection."
17182
17340
  },
17183
17341
  "crosswalk": { "file": "crosswalks/or-v1/nodes.json" },
17184
17342
  "expectedCounts": {},
@@ -56436,7 +56594,7 @@ var catalogue_default = {
56436
56594
  "description": "Park-and-loop routing instances built from real client locations in France, with coordinates and service times in minutes.",
56437
56595
  "domain": "Vehicle routing with time windows",
56438
56596
  "tags": ["location", "duration"],
56439
- "category": "or/v1",
56597
+ "category": "or-set/v1",
56440
56598
  "sources": [{
56441
56599
  "url": "http://www.vrp-rep.org/datasets/download/cabrera-et-al-2021.zip",
56442
56600
  "retrieved": "2026-10-19",
@@ -56449,12 +56607,86 @@ var catalogue_default = {
56449
56607
  "licence": { "kind": "unrecorded" },
56450
56608
  "citations": [],
56451
56609
  "recipe": {
56452
- "status": "not-fetchable",
56453
- "reason": "The download is a collection of separate coordinate files plus a readme, and a collection is more than one or/v1 document, so no recipe reads it."
56610
+ "status": "fetchable",
56611
+ "source": 1,
56612
+ "archive": {
56613
+ "kind": "zip",
56614
+ "members": { "pattern": "Coordinates_\\d+\\.txt" }
56615
+ },
56616
+ "parser": {
56617
+ "format": "csv-table",
56618
+ "encoding": "utf-8",
56619
+ "delimiter": "comma",
56620
+ "skipLines": 0,
56621
+ "idColumn": "ID",
56622
+ "numericColumns": [
56623
+ {
56624
+ "column": "Longitude",
56625
+ "factor": 1
56626
+ },
56627
+ {
56628
+ "column": "Latitude",
56629
+ "factor": 1
56630
+ },
56631
+ {
56632
+ "column": "ServiceTime_min",
56633
+ "factor": 60
56634
+ }
56635
+ ],
56636
+ "columns": [
56637
+ "ServiceTime_min",
56638
+ "Latitude",
56639
+ "Longitude"
56640
+ ]
56641
+ }
56454
56642
  },
56455
- "crosswalk": { "file": "crosswalks/or-v1/nodes.json" },
56456
- "expectedCounts": {},
56457
- "properties": { "surveyId": "or-10" }
56643
+ "crosswalk": {
56644
+ "source": "csv-table",
56645
+ "target": "or-set/v1",
56646
+ "rules": [
56647
+ {
56648
+ "op": "move",
56649
+ "from": "meta",
56650
+ "to": "meta"
56651
+ },
56652
+ {
56653
+ "op": "move",
56654
+ "from": "members[].id",
56655
+ "to": "instances[].id"
56656
+ },
56657
+ {
56658
+ "op": "move",
56659
+ "from": "members[].meta",
56660
+ "to": "instances[].meta"
56661
+ },
56662
+ {
56663
+ "op": "move",
56664
+ "from": "members[].nodes[].id",
56665
+ "to": "instances[].nodes[].id"
56666
+ },
56667
+ {
56668
+ "op": "move",
56669
+ "from": "members[].nodes[].ServiceTime_min",
56670
+ "to": "instances[].nodes[].duration"
56671
+ },
56672
+ {
56673
+ "op": "move",
56674
+ "from": "members[].nodes[].Latitude",
56675
+ "to": "instances[].nodes[].lat"
56676
+ },
56677
+ {
56678
+ "op": "move",
56679
+ "from": "members[].nodes[].Longitude",
56680
+ "to": "instances[].nodes[].lon"
56681
+ }
56682
+ ],
56683
+ "oneWay": []
56684
+ },
56685
+ "expectedCounts": { "instances": 60 },
56686
+ "properties": {
56687
+ "surveyId": "or-10",
56688
+ "timeUnit": "seconds"
56689
+ }
56458
56690
  },
56459
56691
  {
56460
56692
  "id": "vrp-rep-probabilistic-orienteering",
@@ -56593,20 +56825,93 @@ var catalogue_default = {
56593
56825
  "duration",
56594
56826
  "travelTime"
56595
56827
  ],
56596
- "category": "or/v1",
56828
+ "category": "or-set/v1",
56597
56829
  "sources": [{
56598
56830
  "url": "http://www.vrp-rep.org/datasets/download/pillac-et-al-2013.zip",
56599
56831
  "retrieved": "2026-10-19",
56600
56832
  "status": "live"
56833
+ }, {
56834
+ "url": "https://www.vrp-rep.org/datasets/download/pillac-et-al-2013.zip",
56835
+ "retrieved": "2026-10-19",
56836
+ "status": "live"
56601
56837
  }],
56602
56838
  "licence": { "kind": "unrecorded" },
56603
56839
  "citations": [],
56604
56840
  "recipe": {
56605
- "status": "not-fetchable",
56606
- "reason": "The download is a collection of VRP-REP XML instance files holding coordinates and skills but no times, and a collection is more than one or/v1 document, so no recipe reads it."
56841
+ "status": "fetchable",
56842
+ "source": 1,
56843
+ "archive": {
56844
+ "kind": "zip",
56845
+ "members": { "extensions": [".xml"] }
56846
+ },
56847
+ "parser": {
56848
+ "format": "vrp-rep",
56849
+ "encoding": "utf-8"
56850
+ }
56607
56851
  },
56608
- "crosswalk": { "file": "crosswalks/or-v1/nodes.json" },
56609
- "expectedCounts": {},
56852
+ "crosswalk": {
56853
+ "source": "vrp-rep",
56854
+ "target": "or-set/v1",
56855
+ "rules": [
56856
+ {
56857
+ "op": "move",
56858
+ "from": "meta",
56859
+ "to": "meta"
56860
+ },
56861
+ {
56862
+ "op": "move",
56863
+ "from": "members[].id",
56864
+ "to": "instances[].id"
56865
+ },
56866
+ {
56867
+ "op": "move",
56868
+ "from": "members[].meta.dataset",
56869
+ "to": "instances[].meta.dataset"
56870
+ },
56871
+ {
56872
+ "op": "move",
56873
+ "from": "members[].meta.name",
56874
+ "to": "instances[].meta.name"
56875
+ },
56876
+ {
56877
+ "op": "move",
56878
+ "from": "members[].nodes[].id",
56879
+ "to": "instances[].nodes[].id"
56880
+ },
56881
+ {
56882
+ "op": "move",
56883
+ "from": "members[].nodes[].skill",
56884
+ "to": "instances[].nodes[].skill"
56885
+ },
56886
+ {
56887
+ "op": "move",
56888
+ "from": "members[].nodes[].x",
56889
+ "to": "instances[].nodes[].x"
56890
+ },
56891
+ {
56892
+ "op": "move",
56893
+ "from": "members[].nodes[].y",
56894
+ "to": "instances[].nodes[].y"
56895
+ },
56896
+ {
56897
+ "op": "move",
56898
+ "from": "members[].nodes[].type",
56899
+ "to": "instances[].nodes[].type"
56900
+ },
56901
+ {
56902
+ "op": "move",
56903
+ "from": "members[].nodes[].skills",
56904
+ "to": "instances[].nodes[].skills"
56905
+ },
56906
+ {
56907
+ "op": "move",
56908
+ "from": "members[].nodes[].resources",
56909
+ "to": "instances[].nodes[].resources"
56910
+ }
56911
+ ],
56912
+ "oneWay": []
56913
+ },
56914
+ "expectedCounts": { "instances": 57 },
56610
56915
  "properties": { "surveyId": "or-21" }
56611
56916
  },
56612
56917
  {
@@ -57655,6 +57960,10 @@ var catalogue_default = {
57655
57960
  "url": "https://zenodo.org/records/5823834",
57656
57961
  "retrieved": "2026-10-19",
57657
57962
  "status": "live"
57963
+ }, {
57964
+ "url": "https://zenodo.org/records/5823834/files/MeterReading_Instance.zip?download=1",
57965
+ "retrieved": "2026-10-19",
57966
+ "status": "live"
57658
57967
  }],
57659
57968
  "licence": {
57660
57969
  "kind": "spdx",
@@ -57662,11 +57971,45 @@ var catalogue_default = {
57662
57971
  },
57663
57972
  "citations": [],
57664
57973
  "recipe": {
57665
- "status": "not-fetchable",
57666
- "reason": "The download is one arc routing instance in two tab separated text files with no column names, holding only planar coordinates of customers and a road network, so there is no field of the or/v1 node beyond a position and no table the parser reads."
57974
+ "status": "fetchable",
57975
+ "source": 1,
57976
+ "archive": {
57977
+ "kind": "zip",
57978
+ "member": { "path": "customers.txt" }
57979
+ },
57980
+ "parser": {
57981
+ "format": "customer-points",
57982
+ "encoding": "utf-8"
57983
+ }
57667
57984
  },
57668
- "crosswalk": { "file": "crosswalks/or-v1/nodes.json" },
57669
- "expectedCounts": {},
57985
+ "crosswalk": {
57986
+ "source": "customer-points",
57987
+ "target": "or/v1",
57988
+ "rules": [
57989
+ {
57990
+ "op": "move",
57991
+ "from": "meta",
57992
+ "to": "meta"
57993
+ },
57994
+ {
57995
+ "op": "move",
57996
+ "from": "nodes[].id",
57997
+ "to": "nodes[].id"
57998
+ },
57999
+ {
58000
+ "op": "move",
58001
+ "from": "nodes[].x",
58002
+ "to": "nodes[].x"
58003
+ },
58004
+ {
58005
+ "op": "move",
58006
+ "from": "nodes[].y",
58007
+ "to": "nodes[].y"
58008
+ }
58009
+ ],
58010
+ "oneWay": []
58011
+ },
58012
+ "expectedCounts": { "nodes": 6067 },
57670
58013
  "properties": { "surveyId": "or-6" }
57671
58014
  },
57672
58015
  {
@@ -57734,7 +58077,7 @@ var catalogue_default = {
57734
58077
  "citations": [],
57735
58078
  "recipe": {
57736
58079
  "status": "not-fetchable",
57737
- "reason": "The Zenodo files are a custom sectioned text format (technicians, tasks and a travel time matrix of millions of lines) and not a table, and two of them are collections of instance files."
58080
+ "reason": "The instances are a custom sectioned text format whose tasks have no positions, and the collection is hundreds of megabytes compressed, almost all of it a pairwise travel time matrix that or/v1 has no arcs to hold, so reading it would hold gigabytes in memory to keep a few fields per task."
57738
58081
  },
57739
58082
  "crosswalk": { "file": "crosswalks/or-v1/nodes.json" },
57740
58083
  "expectedCounts": {},