@particle-academy/fancy-conformance 0.14.0 → 0.15.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/VERSION +1 -1
- package/package.json +1 -1
- package/suites/expr/evaluate/cases.json +186 -0
- package/suites/expr/evaluate/manifest.json +17 -4
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.15.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@particle-academy/fancy-conformance",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Shared cross-language conformance fixtures for the Fancy suite. One contract, N implementations, and a single table that every implementation asserts in its own CI \u2014 so 'parity' is a test result rather than a claim. Ships the fixture data itself, so a Rust, Go or Python runner can consume it without a JavaScript toolchain.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -1243,6 +1243,192 @@
|
|
|
1243
1243
|
"ok": false
|
|
1244
1244
|
},
|
|
1245
1245
|
"notes": "Sandboxing is a security property, not a style preference: these expressions arrive from end users and from agents, over the wire. No calls, no host reach, in any implementation."
|
|
1246
|
+
},
|
|
1247
|
+
{
|
|
1248
|
+
"id": "0901-array-length",
|
|
1249
|
+
"title": "`.length` counts an array.",
|
|
1250
|
+
"since": "0.15.0",
|
|
1251
|
+
"tags": [
|
|
1252
|
+
"expr",
|
|
1253
|
+
"length"
|
|
1254
|
+
],
|
|
1255
|
+
"input": {
|
|
1256
|
+
"expression": "in.items.length",
|
|
1257
|
+
"context": {
|
|
1258
|
+
"in": {
|
|
1259
|
+
"content": "hello",
|
|
1260
|
+
"count": 3,
|
|
1261
|
+
"deal_id": "D-1",
|
|
1262
|
+
"transcript": null,
|
|
1263
|
+
"items": [
|
|
1264
|
+
1,
|
|
1265
|
+
2
|
|
1266
|
+
],
|
|
1267
|
+
"empty": [],
|
|
1268
|
+
"obj": {},
|
|
1269
|
+
"flag": true,
|
|
1270
|
+
"zero": 0,
|
|
1271
|
+
"blank": ""
|
|
1272
|
+
},
|
|
1273
|
+
"user": {
|
|
1274
|
+
"name": "Ada"
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
},
|
|
1278
|
+
"expected": {
|
|
1279
|
+
"ok": true,
|
|
1280
|
+
"value": 2
|
|
1281
|
+
},
|
|
1282
|
+
"notes": "The one pseudo-property, and it is load-bearing: `[]` is TRUTHY (0301), so without `.length` a consumer has no way to ask whether a collection is empty. The grammar would assert that an array which exists is a value and then leave nobody able to test the thing they care about."
|
|
1283
|
+
},
|
|
1284
|
+
{
|
|
1285
|
+
"id": "0902-empty-array-length",
|
|
1286
|
+
"title": "An empty array has length 0 while still being truthy.",
|
|
1287
|
+
"since": "0.15.0",
|
|
1288
|
+
"tags": [
|
|
1289
|
+
"expr",
|
|
1290
|
+
"length"
|
|
1291
|
+
],
|
|
1292
|
+
"input": {
|
|
1293
|
+
"expression": "in.empty.length",
|
|
1294
|
+
"context": {
|
|
1295
|
+
"in": {
|
|
1296
|
+
"content": "hello",
|
|
1297
|
+
"count": 3,
|
|
1298
|
+
"deal_id": "D-1",
|
|
1299
|
+
"transcript": null,
|
|
1300
|
+
"items": [
|
|
1301
|
+
1,
|
|
1302
|
+
2
|
|
1303
|
+
],
|
|
1304
|
+
"empty": [],
|
|
1305
|
+
"obj": {},
|
|
1306
|
+
"flag": true,
|
|
1307
|
+
"zero": 0,
|
|
1308
|
+
"blank": ""
|
|
1309
|
+
},
|
|
1310
|
+
"user": {
|
|
1311
|
+
"name": "Ada"
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
},
|
|
1315
|
+
"expected": {
|
|
1316
|
+
"ok": true,
|
|
1317
|
+
"value": 0
|
|
1318
|
+
},
|
|
1319
|
+
"notes": "The pair that makes the truthiness decision coherent: truthy AND countable. An implementation that made [] falsy would pass this row and fail 0301."
|
|
1320
|
+
},
|
|
1321
|
+
{
|
|
1322
|
+
"id": "0903-string-length",
|
|
1323
|
+
"title": "`.length` counts a string.",
|
|
1324
|
+
"since": "0.15.0",
|
|
1325
|
+
"tags": [
|
|
1326
|
+
"expr",
|
|
1327
|
+
"length"
|
|
1328
|
+
],
|
|
1329
|
+
"input": {
|
|
1330
|
+
"expression": "in.content.length",
|
|
1331
|
+
"context": {
|
|
1332
|
+
"in": {
|
|
1333
|
+
"content": "hello",
|
|
1334
|
+
"count": 3,
|
|
1335
|
+
"deal_id": "D-1",
|
|
1336
|
+
"transcript": null,
|
|
1337
|
+
"items": [
|
|
1338
|
+
1,
|
|
1339
|
+
2
|
|
1340
|
+
],
|
|
1341
|
+
"empty": [],
|
|
1342
|
+
"obj": {},
|
|
1343
|
+
"flag": true,
|
|
1344
|
+
"zero": 0,
|
|
1345
|
+
"blank": ""
|
|
1346
|
+
},
|
|
1347
|
+
"user": {
|
|
1348
|
+
"name": "Ada"
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
},
|
|
1352
|
+
"expected": {
|
|
1353
|
+
"ok": true,
|
|
1354
|
+
"value": 5
|
|
1355
|
+
}
|
|
1356
|
+
},
|
|
1357
|
+
{
|
|
1358
|
+
"id": "0904-object-has-no-length",
|
|
1359
|
+
"title": "An object has NO `.length`.",
|
|
1360
|
+
"since": "0.15.0",
|
|
1361
|
+
"tags": [
|
|
1362
|
+
"expr",
|
|
1363
|
+
"length",
|
|
1364
|
+
"deliberate"
|
|
1365
|
+
],
|
|
1366
|
+
"input": {
|
|
1367
|
+
"expression": "in.obj.length",
|
|
1368
|
+
"context": {
|
|
1369
|
+
"in": {
|
|
1370
|
+
"content": "hello",
|
|
1371
|
+
"count": 3,
|
|
1372
|
+
"deal_id": "D-1",
|
|
1373
|
+
"transcript": null,
|
|
1374
|
+
"items": [
|
|
1375
|
+
1,
|
|
1376
|
+
2
|
|
1377
|
+
],
|
|
1378
|
+
"empty": [],
|
|
1379
|
+
"obj": {},
|
|
1380
|
+
"flag": true,
|
|
1381
|
+
"zero": 0,
|
|
1382
|
+
"blank": ""
|
|
1383
|
+
},
|
|
1384
|
+
"user": {
|
|
1385
|
+
"name": "Ada"
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
},
|
|
1389
|
+
"expected": {
|
|
1390
|
+
"ok": true,
|
|
1391
|
+
"value": null
|
|
1392
|
+
},
|
|
1393
|
+
"notes": "Deliberate. There is no count three languages would agree on for an object, and an object used as a collection is rare enough not to justify inventing one. Null here is the ordinary absent-path answer, not a special case."
|
|
1394
|
+
},
|
|
1395
|
+
{
|
|
1396
|
+
"id": "0905-length-is-not-host-reach",
|
|
1397
|
+
"title": "No other host property is reachable.",
|
|
1398
|
+
"since": "0.15.0",
|
|
1399
|
+
"tags": [
|
|
1400
|
+
"expr",
|
|
1401
|
+
"length",
|
|
1402
|
+
"sandbox"
|
|
1403
|
+
],
|
|
1404
|
+
"input": {
|
|
1405
|
+
"expression": "in.items.constructor",
|
|
1406
|
+
"context": {
|
|
1407
|
+
"in": {
|
|
1408
|
+
"content": "hello",
|
|
1409
|
+
"count": 3,
|
|
1410
|
+
"deal_id": "D-1",
|
|
1411
|
+
"transcript": null,
|
|
1412
|
+
"items": [
|
|
1413
|
+
1,
|
|
1414
|
+
2
|
|
1415
|
+
],
|
|
1416
|
+
"empty": [],
|
|
1417
|
+
"obj": {},
|
|
1418
|
+
"flag": true,
|
|
1419
|
+
"zero": 0,
|
|
1420
|
+
"blank": ""
|
|
1421
|
+
},
|
|
1422
|
+
"user": {
|
|
1423
|
+
"name": "Ada"
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
},
|
|
1427
|
+
"expected": {
|
|
1428
|
+
"ok": true,
|
|
1429
|
+
"value": null
|
|
1430
|
+
},
|
|
1431
|
+
"notes": "`.length` is a computed count, not an opening. Nothing else on the prototype chain resolves -- these expressions arrive from end users and from agents, over the wire."
|
|
1246
1432
|
}
|
|
1247
1433
|
]
|
|
1248
1434
|
}
|
|
@@ -11,9 +11,21 @@
|
|
|
11
11
|
"reference": "node",
|
|
12
12
|
"referenceNote": "No implementation exists yet in any language. This table is written FIRST and every implementation is built against it, which is the whole argument for owning the grammar rather than adopting three libraries that disagree.",
|
|
13
13
|
"implementations": [
|
|
14
|
-
{
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
{
|
|
15
|
+
"language": "node",
|
|
16
|
+
"package": "@particle-academy/fancy-expr",
|
|
17
|
+
"symbol": "evaluate"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"language": "php",
|
|
21
|
+
"package": "particle-academy/fancy-expr",
|
|
22
|
+
"symbol": "FancyExpr\\Expr::evaluate"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"language": "python",
|
|
26
|
+
"package": "fancy-expr",
|
|
27
|
+
"symbol": "fancy_expr.evaluate"
|
|
28
|
+
}
|
|
17
29
|
]
|
|
18
30
|
},
|
|
19
31
|
"notes": [
|
|
@@ -23,6 +35,7 @@
|
|
|
23
35
|
"`==` AND `===` ARE THE SAME OPERATOR (0501-0503), and neither coerces. Both spellings are accepted because authors write both. Two equality operators that differ subtly is a language that generates bug reports, and there are three runtimes to keep in step.",
|
|
24
36
|
"`&&` AND `||` RETURN THE OPERAND, NOT A BOOLEAN (0401-0404). That is what makes `in.transcript || in.content` a useful fallback rather than merely `true` — and the reported production case wrote exactly that shape.",
|
|
25
37
|
"MALFORMED EXPRESSIONS FAIL (0801-0805) and never return null. A null there would be indistinguishable from an absent path, which is the defect being removed. 0805 pins that a function call does not parse: sandboxing is a security property here, not a style preference, because these expressions arrive from end users and from agents over the wire.",
|
|
26
|
-
"This suite needs DISCRIMINATION PROBES before it can claim more than drift-guarding — deliberately-wrong evaluators that must each fail an exact set of ids. Notably: one that uses native truthiness (must fail 0301/0302), one that coerces on `==` (must fail 0503), and one that returns booleans from `&&`/`||` (must fail 0401/0403/0404). Not yet written; recorded so a green tick is not read as the stronger claim."
|
|
38
|
+
"This suite needs DISCRIMINATION PROBES before it can claim more than drift-guarding — deliberately-wrong evaluators that must each fail an exact set of ids. Notably: one that uses native truthiness (must fail 0301/0302), one that coerces on `==` (must fail 0503), and one that returns booleans from `&&`/`||` (must fail 0401/0403/0404). Not yet written; recorded so a green tick is not read as the stronger claim.",
|
|
39
|
+
"`.length` (0901-0905) IS the one pseudo-property, and it is load-bearing rather than convenient. Because `[]` is TRUTHY, a consumer with no `.length` would have no way to ask whether a collection is EMPTY -- the grammar would assert that an array which exists is a value and then leave nobody able to test the thing they care about. It is a computed count, not host reach: nothing is called and no prototype is walked, and 0905 pins that nothing else on the chain resolves. Objects deliberately have none (0904), since no count would survive three languages. These rows were added after writing the reference implementation's discrimination tests found the SPEC contradicting the CODE -- the truthiness rule was justified with `.length` while `.length` returned null."
|
|
27
40
|
]
|
|
28
41
|
}
|