@entelekheia/ref-id 0.1.1 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@entelekheia/ref-id",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "The ref: identifier scheme — a specification published as data with conformance vectors, and the package that consumes it.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -32,7 +32,7 @@
32
32
  "publishConfig": {
33
33
  "access": "public",
34
34
  "registry": "https://registry.npmjs.org",
35
- "provenance": false
35
+ "provenance": true
36
36
  },
37
37
  "repository": {
38
38
  "type": "git",
package/spec/ref-id.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "specVersion": "1.1.0",
2
+ "specVersion": "1.2.0",
3
3
  "scheme": "ref",
4
4
  "grammar": {
5
5
  "dialect": "ecmascript-2018",
@@ -128,6 +128,14 @@
128
128
  "declaredBy": "the agent identifier grammar namespace/name[:version]: the namespace is a domain, a platform/user under a domain, a mailbox, or the literal unknown; the ~digest of the full form is carried by state= instead",
129
129
  "corpus": "the agent bundle",
130
130
  "reference": "dot-agent agent-id reference"
131
+ },
132
+ "ai-model": {
133
+ "locator": "served-model-id",
134
+ "validator": "declared-name",
135
+ "delegate": "verbatim",
136
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._:@-]*(?:/[A-Za-z0-9][A-Za-z0-9._:@-]*)*$",
137
+ "declaredBy": "the id the model is served under — the exact string a caller sends to the serving process to select it, verbatim. Deliberately permissive: coercing a served name breaks the round-trip that makes it an identifier at all, so ':' (an Ollama tag), '/' (a hub-style namespace) and '@' (an LM Studio quantisation key, a revision pin) are all admitted, because a serving process accepts each of them today and rejecting one would be a defect rather than a safeguard. Every '/'-separated segment must open on an alphanumeric, which admits each of those and excludes '..', '//' and a trailing '/': the delegate is verbatim, so a consumer mapping a served id onto a path — a local weights cache — would otherwise inherit a traversal from a locator that parsed clean. Case is significant and there is no normalisation, which is a decision with no way back: two callers naming one model in two casings mint two identifiers, and adding a fold later would be a change to normalisation, which mints identifier version 2.",
138
+ "reference": "no published grammar names a hosted API model: Package URL registers artifact-registry namespaces only (huggingface, mlflow), CycloneDX carries the category as a component type and identifies with an ordinary purl, SPDX 3.0's AIPackage identifies by free-text name and delegates to packageUrl, and OpenTelemetry's gen_ai.request.model is explicitly free text — so this type is this specification's own, not a delegation."
131
139
  }
132
140
  },
133
141
  "typeRegistry": "a type names the naming system that owns the locator grammar; an unregistered type parses to uncovered, never to malformed, and registering its validator here is what promotes it — the registry is this table",
@@ -190,7 +198,8 @@
190
198
  "role": "population",
191
199
  "forms": [
192
200
  "ref",
193
- "sha256"
201
+ "sha256",
202
+ "unknown"
194
203
  ]
195
204
  },
196
205
  "when": {
@@ -229,6 +238,10 @@
229
238
  "nested": true,
230
239
  "depth": 1,
231
240
  "encoding": "nested"
241
+ },
242
+ "unknown": {
243
+ "pattern": "^unknown$",
244
+ "reference": "the declared level for a population nobody established. Deliberately not `none`, which `state` uses: a state cannot be empty, so `none` is unambiguous there, while a population over zero members is a real and different thing from a population nobody recorded — and an identifier must not let the two read alike. It is a floor, never a destination: a producer that can enumerate its population says so with `sha256`, which names which population rather than admitting there was one"
232
245
  }
233
246
  },
234
247
  "refinements": {
@@ -1127,6 +1140,259 @@
1127
1140
  "status": "malformed",
1128
1141
  "part": "locator"
1129
1142
  }
1143
+ },
1144
+ {
1145
+ "name": "ai-model served id is admitted: Qwen3-4B-Instruct-2507-4bit",
1146
+ "input": "ref:ai-model:Qwen3-4B-Instruct-2507-4bit",
1147
+ "expect": {
1148
+ "status": "ok",
1149
+ "version": 1,
1150
+ "qualifiers": [],
1151
+ "fragment": null,
1152
+ "type": "ai-model",
1153
+ "locator": "Qwen3-4B-Instruct-2507-4bit"
1154
+ }
1155
+ },
1156
+ {
1157
+ "name": "ai-model served id is admitted: gemma-4-26b-a4b-it-4bit",
1158
+ "input": "ref:ai-model:gemma-4-26b-a4b-it-4bit",
1159
+ "expect": {
1160
+ "status": "ok",
1161
+ "version": 1,
1162
+ "qualifiers": [],
1163
+ "fragment": null,
1164
+ "type": "ai-model",
1165
+ "locator": "gemma-4-26b-a4b-it-4bit"
1166
+ }
1167
+ },
1168
+ {
1169
+ "name": "ai-model served id is admitted: Qwen3.5-9B-OptiQ-4bit",
1170
+ "input": "ref:ai-model:Qwen3.5-9B-OptiQ-4bit",
1171
+ "expect": {
1172
+ "status": "ok",
1173
+ "version": 1,
1174
+ "qualifiers": [],
1175
+ "fragment": null,
1176
+ "type": "ai-model",
1177
+ "locator": "Qwen3.5-9B-OptiQ-4bit"
1178
+ }
1179
+ },
1180
+ {
1181
+ "name": "ai-model served id is admitted: gpt-oss-20b-MXFP4-Q8",
1182
+ "input": "ref:ai-model:gpt-oss-20b-MXFP4-Q8",
1183
+ "expect": {
1184
+ "status": "ok",
1185
+ "version": 1,
1186
+ "qualifiers": [],
1187
+ "fragment": null,
1188
+ "type": "ai-model",
1189
+ "locator": "gpt-oss-20b-MXFP4-Q8"
1190
+ }
1191
+ },
1192
+ {
1193
+ "name": "ai-model served id is admitted: Llama-3.2-1B-Instruct-4bit",
1194
+ "input": "ref:ai-model:Llama-3.2-1B-Instruct-4bit",
1195
+ "expect": {
1196
+ "status": "ok",
1197
+ "version": 1,
1198
+ "qualifiers": [],
1199
+ "fragment": null,
1200
+ "type": "ai-model",
1201
+ "locator": "Llama-3.2-1B-Instruct-4bit"
1202
+ }
1203
+ },
1204
+ {
1205
+ "name": "ai-model served id is admitted: Qwen3.5-27B-Claude-4.6-Opus-Distilled-MLX-4bit",
1206
+ "input": "ref:ai-model:Qwen3.5-27B-Claude-4.6-Opus-Distilled-MLX-4bit",
1207
+ "expect": {
1208
+ "status": "ok",
1209
+ "version": 1,
1210
+ "qualifiers": [],
1211
+ "fragment": null,
1212
+ "type": "ai-model",
1213
+ "locator": "Qwen3.5-27B-Claude-4.6-Opus-Distilled-MLX-4bit"
1214
+ }
1215
+ },
1216
+ {
1217
+ "name": "ai-model served id is admitted: SmolLM3-3B-4bit",
1218
+ "input": "ref:ai-model:SmolLM3-3B-4bit",
1219
+ "expect": {
1220
+ "status": "ok",
1221
+ "version": 1,
1222
+ "qualifiers": [],
1223
+ "fragment": null,
1224
+ "type": "ai-model",
1225
+ "locator": "SmolLM3-3B-4bit"
1226
+ }
1227
+ },
1228
+ {
1229
+ "name": "ai-model served id is admitted: T-mixed-gemma-4-12B-it-OptiQ-4bit",
1230
+ "input": "ref:ai-model:T-mixed-gemma-4-12B-it-OptiQ-4bit",
1231
+ "expect": {
1232
+ "status": "ok",
1233
+ "version": 1,
1234
+ "qualifiers": [],
1235
+ "fragment": null,
1236
+ "type": "ai-model",
1237
+ "locator": "T-mixed-gemma-4-12B-it-OptiQ-4bit"
1238
+ }
1239
+ },
1240
+ {
1241
+ "name": "ai-model served id is admitted: claude-opus-5",
1242
+ "input": "ref:ai-model:claude-opus-5",
1243
+ "expect": {
1244
+ "status": "ok",
1245
+ "version": 1,
1246
+ "qualifiers": [],
1247
+ "fragment": null,
1248
+ "type": "ai-model",
1249
+ "locator": "claude-opus-5"
1250
+ }
1251
+ },
1252
+ {
1253
+ "name": "ai-model served id is admitted: Ternary-Bonsai-27B-mlx-2bit",
1254
+ "input": "ref:ai-model:Ternary-Bonsai-27B-mlx-2bit",
1255
+ "expect": {
1256
+ "status": "ok",
1257
+ "version": 1,
1258
+ "qualifiers": [],
1259
+ "fragment": null,
1260
+ "type": "ai-model",
1261
+ "locator": "Ternary-Bonsai-27B-mlx-2bit"
1262
+ }
1263
+ },
1264
+ {
1265
+ "name": "ai-model served id is admitted: gemini-2.5-flash",
1266
+ "input": "ref:ai-model:gemini-2.5-flash",
1267
+ "expect": {
1268
+ "status": "ok",
1269
+ "version": 1,
1270
+ "qualifiers": [],
1271
+ "fragment": null,
1272
+ "type": "ai-model",
1273
+ "locator": "gemini-2.5-flash"
1274
+ }
1275
+ },
1276
+ {
1277
+ "name": "ai-model served id is admitted: llama3:8b",
1278
+ "input": "ref:ai-model:llama3:8b",
1279
+ "expect": {
1280
+ "status": "ok",
1281
+ "version": 1,
1282
+ "qualifiers": [],
1283
+ "fragment": null,
1284
+ "type": "ai-model",
1285
+ "locator": "llama3:8b"
1286
+ }
1287
+ },
1288
+ {
1289
+ "name": "ai-model served id is admitted: gpt-4o-2024-08-06",
1290
+ "input": "ref:ai-model:gpt-4o-2024-08-06",
1291
+ "expect": {
1292
+ "status": "ok",
1293
+ "version": 1,
1294
+ "qualifiers": [],
1295
+ "fragment": null,
1296
+ "type": "ai-model",
1297
+ "locator": "gpt-4o-2024-08-06"
1298
+ }
1299
+ },
1300
+ {
1301
+ "name": "ai-model served id is admitted: mlx-community/Qwen3-1.7B-4bit",
1302
+ "input": "ref:ai-model:mlx-community/Qwen3-1.7B-4bit",
1303
+ "expect": {
1304
+ "status": "ok",
1305
+ "version": 1,
1306
+ "qualifiers": [],
1307
+ "fragment": null,
1308
+ "type": "ai-model",
1309
+ "locator": "mlx-community/Qwen3-1.7B-4bit"
1310
+ }
1311
+ },
1312
+ {
1313
+ "name": "an ai-model id cannot open on a separator",
1314
+ "input": "ref:ai-model:-Qwen3-4B",
1315
+ "expect": {
1316
+ "status": "malformed",
1317
+ "part": "locator"
1318
+ }
1319
+ },
1320
+ {
1321
+ "name": "unknown is a declared population level",
1322
+ "input": "ref:folder:acme-tools;over=unknown",
1323
+ "expect": {
1324
+ "status": "ok",
1325
+ "version": 1,
1326
+ "qualifiers": [
1327
+ [
1328
+ "over",
1329
+ "unknown"
1330
+ ]
1331
+ ],
1332
+ "fragment": null,
1333
+ "type": "folder",
1334
+ "locator": "acme-tools"
1335
+ }
1336
+ },
1337
+ {
1338
+ "name": "none is not a population level — a population of zero is not a population nobody recorded",
1339
+ "input": "ref:folder:acme-tools;over=none",
1340
+ "expect": {
1341
+ "status": "malformed",
1342
+ "part": "over"
1343
+ }
1344
+ },
1345
+ {
1346
+ "name": "unknown is not a state level — the fence from the other side",
1347
+ "input": "ref:folder:acme-tools;state=unknown",
1348
+ "expect": {
1349
+ "status": "malformed",
1350
+ "part": "state"
1351
+ }
1352
+ },
1353
+ {
1354
+ "name": "unknown is declared for over alone, never for by",
1355
+ "input": "ref:folder:acme-tools;by=unknown",
1356
+ "expect": {
1357
+ "status": "malformed",
1358
+ "part": "by"
1359
+ }
1360
+ },
1361
+ {
1362
+ "name": "an ai-model id cannot carry a character outside its declared class",
1363
+ "input": "ref:ai-model:a b",
1364
+ "expect": {
1365
+ "status": "malformed",
1366
+ "part": "locator"
1367
+ }
1368
+ },
1369
+ {
1370
+ "name": "an ai-model id carries a quantisation key after @",
1371
+ "input": "ref:ai-model:qwen2.5-7b-instruct@q4_k_m",
1372
+ "expect": {
1373
+ "status": "ok",
1374
+ "version": 1,
1375
+ "type": "ai-model",
1376
+ "locator": "qwen2.5-7b-instruct@q4_k_m",
1377
+ "qualifiers": [],
1378
+ "fragment": null
1379
+ }
1380
+ },
1381
+ {
1382
+ "name": "an ai-model id cannot traverse — every segment opens on an alphanumeric",
1383
+ "input": "ref:ai-model:a/../../etc/passwd",
1384
+ "expect": {
1385
+ "status": "malformed",
1386
+ "part": "locator"
1387
+ }
1388
+ },
1389
+ {
1390
+ "name": "an ai-model id cannot carry an empty segment",
1391
+ "input": "ref:ai-model:a//b",
1392
+ "expect": {
1393
+ "status": "malformed",
1394
+ "part": "locator"
1395
+ }
1130
1396
  }
1131
1397
  ],
1132
1398
  "roundtrip": [
@@ -1149,7 +1415,10 @@
1149
1415
  "ref:pkg:npm/acme-tools#acme/adr@2/0019",
1150
1416
  "ref:folder:acme-tools;by=ref:2:pkg:npm/x@1.0.0",
1151
1417
  "ref:doi:10.1000/182;state=swh:1:rev:7e29bb6000000000000000000000000000000000#S",
1152
- "ref:folder:acme-tools;by=ref:pkg:npm/x@1.0.0%2523src/y"
1418
+ "ref:folder:acme-tools;by=ref:pkg:npm/x@1.0.0%2523src/y",
1419
+ "ref:ai-model:mlx-community/Qwen3-1.7B-4bit",
1420
+ "ref:ai-model:llama3:8b",
1421
+ "ref:folder:acme-tools;over=unknown"
1153
1422
  ],
1154
1423
  "build": [
1155
1424
  {
@@ -1300,6 +1569,36 @@
1300
1569
  ]
1301
1570
  },
1302
1571
  "expect": "ref:folder:acme-tools;over=sha256:41b9caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1572
+ },
1573
+ {
1574
+ "name": "an ai-model locator with a hub-style separator builds as is",
1575
+ "parts": {
1576
+ "type": "ai-model",
1577
+ "locator": "mlx-community/Qwen3-1.7B-4bit"
1578
+ },
1579
+ "expect": "ref:ai-model:mlx-community/Qwen3-1.7B-4bit"
1580
+ },
1581
+ {
1582
+ "name": "an ai-model locator with an Ollama tag builds as is",
1583
+ "parts": {
1584
+ "type": "ai-model",
1585
+ "locator": "llama3:8b"
1586
+ },
1587
+ "expect": "ref:ai-model:llama3:8b"
1588
+ },
1589
+ {
1590
+ "name": "over=unknown builds as the declared level for an unestablished population",
1591
+ "parts": {
1592
+ "type": "folder",
1593
+ "locator": "acme-tools",
1594
+ "qualifiers": [
1595
+ [
1596
+ "over",
1597
+ "unknown"
1598
+ ]
1599
+ ]
1600
+ },
1601
+ "expect": "ref:folder:acme-tools;over=unknown"
1303
1602
  }
1304
1603
  ],
1305
1604
  "digest": [
@@ -1 +1 @@
1
- c58f36a43416e5422235e8d92920d4d82581601deed69169901291938c5e2727
1
+ ee34597292d313a7c424d09c050d2e1bf6cc9507b9b2627f63c684131c6fd3c6