@dzhechkov/harness-core 0.8.47 → 0.8.49
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/.dz-manifest.json +57 -37
- package/README.md +69 -4
- package/dist/publish.d.ts +1 -1
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +2 -2
- package/dist/release-line.d.ts +1 -6
- package/dist/release-line.d.ts.map +1 -1
- package/dist/release-line.js +11 -13
- package/dist/release-line.js.map +1 -1
- package/dist/setup-memory-deps.d.ts +14 -0
- package/dist/setup-memory-deps.d.ts.map +1 -0
- package/dist/setup-memory-deps.js +210 -0
- package/dist/setup-memory-deps.js.map +1 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +379 -378
- package/dist/setup.js.map +1 -1
- package/dist/stage-usage.d.ts +102 -2
- package/dist/stage-usage.d.ts.map +1 -1
- package/dist/stage-usage.js +252 -2
- package/dist/stage-usage.js.map +1 -1
- package/dist/test-receipt.d.ts +4 -2
- package/dist/test-receipt.d.ts.map +1 -1
- package/dist/test-receipt.js +97 -3
- package/dist/test-receipt.js.map +1 -1
- package/dist/workflow-run-dispatch.d.ts +15 -0
- package/dist/workflow-run-dispatch.d.ts.map +1 -1
- package/dist/workflow-run-dispatch.js +50 -8
- package/dist/workflow-run-dispatch.js.map +1 -1
- package/dist/workflow-run.d.ts +8 -1
- package/dist/workflow-run.d.ts.map +1 -1
- package/dist/workflow-run.js +64 -0
- package/dist/workflow-run.js.map +1 -1
- package/package.json +1 -1
- package/sbom.json +86 -36
- package/src/publish.ts +3 -3
- package/src/release-line.ts +11 -13
- package/src/setup-memory-deps.ts +166 -0
- package/src/setup.ts +95 -98
- package/src/stage-usage.ts +196 -2
- package/src/test-receipt.ts +90 -4
- package/src/workflow-run-dispatch.ts +50 -5
- package/src/workflow-run.ts +61 -1
package/sbom.json
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"hashes": [
|
|
26
26
|
{
|
|
27
27
|
"alg": "SHA-256",
|
|
28
|
-
"content": "
|
|
28
|
+
"content": "f21bb94bff3cdda978c5309a39f76c280ac699c21fa231490192c6b9dcde1ba6"
|
|
29
29
|
}
|
|
30
30
|
]
|
|
31
31
|
},
|
|
@@ -4795,7 +4795,7 @@
|
|
|
4795
4795
|
"hashes": [
|
|
4796
4796
|
{
|
|
4797
4797
|
"alg": "SHA-256",
|
|
4798
|
-
"content": "
|
|
4798
|
+
"content": "40975c8defdaf041e61135a2bd85b05ff45c95441cc6a6807d1ae6b1e455b6a5"
|
|
4799
4799
|
}
|
|
4800
4800
|
]
|
|
4801
4801
|
},
|
|
@@ -4805,7 +4805,7 @@
|
|
|
4805
4805
|
"hashes": [
|
|
4806
4806
|
{
|
|
4807
4807
|
"alg": "SHA-256",
|
|
4808
|
-
"content": "
|
|
4808
|
+
"content": "1fd51135dbd973f5958177d1c1e2f44e8c7c5331af8bab3eb87ed83e0d7326f2"
|
|
4809
4809
|
}
|
|
4810
4810
|
]
|
|
4811
4811
|
},
|
|
@@ -4815,7 +4815,7 @@
|
|
|
4815
4815
|
"hashes": [
|
|
4816
4816
|
{
|
|
4817
4817
|
"alg": "SHA-256",
|
|
4818
|
-
"content": "
|
|
4818
|
+
"content": "9d6820cb54a7dc7355901c7c4efe0acbe694fa86c6cd8c2f3d529e35ceba2975"
|
|
4819
4819
|
}
|
|
4820
4820
|
]
|
|
4821
4821
|
},
|
|
@@ -5275,7 +5275,7 @@
|
|
|
5275
5275
|
"hashes": [
|
|
5276
5276
|
{
|
|
5277
5277
|
"alg": "SHA-256",
|
|
5278
|
-
"content": "
|
|
5278
|
+
"content": "adab2e7a85dd1e745e2b20bd3574e64025a2d1946dc5124f59ac367f051cd677"
|
|
5279
5279
|
}
|
|
5280
5280
|
]
|
|
5281
5281
|
},
|
|
@@ -5285,7 +5285,7 @@
|
|
|
5285
5285
|
"hashes": [
|
|
5286
5286
|
{
|
|
5287
5287
|
"alg": "SHA-256",
|
|
5288
|
-
"content": "
|
|
5288
|
+
"content": "a4607f5d06ee27c02f0167f202a4a81c11a61e1773ff2ab4914700575f5087cf"
|
|
5289
5289
|
}
|
|
5290
5290
|
]
|
|
5291
5291
|
},
|
|
@@ -5295,7 +5295,7 @@
|
|
|
5295
5295
|
"hashes": [
|
|
5296
5296
|
{
|
|
5297
5297
|
"alg": "SHA-256",
|
|
5298
|
-
"content": "
|
|
5298
|
+
"content": "f62708bb4eecba718eea02eaa5d78553bf2c8b9ecb93fd0858dff19ca94c1dd0"
|
|
5299
5299
|
}
|
|
5300
5300
|
]
|
|
5301
5301
|
},
|
|
@@ -5305,7 +5305,7 @@
|
|
|
5305
5305
|
"hashes": [
|
|
5306
5306
|
{
|
|
5307
5307
|
"alg": "SHA-256",
|
|
5308
|
-
"content": "
|
|
5308
|
+
"content": "46215c2e0b6f6ce4762a1682f8db867752309640681470ab227776667e475e87"
|
|
5309
5309
|
}
|
|
5310
5310
|
]
|
|
5311
5311
|
},
|
|
@@ -6069,13 +6069,53 @@
|
|
|
6069
6069
|
}
|
|
6070
6070
|
]
|
|
6071
6071
|
},
|
|
6072
|
+
{
|
|
6073
|
+
"type": "file",
|
|
6074
|
+
"name": "dist/setup-memory-deps.d.ts",
|
|
6075
|
+
"hashes": [
|
|
6076
|
+
{
|
|
6077
|
+
"alg": "SHA-256",
|
|
6078
|
+
"content": "20c587d44266b94bc946c25d66c1e53dbd57dfbbba49a56eb7e5080b89bffadb"
|
|
6079
|
+
}
|
|
6080
|
+
]
|
|
6081
|
+
},
|
|
6082
|
+
{
|
|
6083
|
+
"type": "file",
|
|
6084
|
+
"name": "dist/setup-memory-deps.d.ts.map",
|
|
6085
|
+
"hashes": [
|
|
6086
|
+
{
|
|
6087
|
+
"alg": "SHA-256",
|
|
6088
|
+
"content": "28de3a30d51b04b29392175bdc69c8c47aa4b8bd314182b631343e14144ebadf"
|
|
6089
|
+
}
|
|
6090
|
+
]
|
|
6091
|
+
},
|
|
6092
|
+
{
|
|
6093
|
+
"type": "file",
|
|
6094
|
+
"name": "dist/setup-memory-deps.js",
|
|
6095
|
+
"hashes": [
|
|
6096
|
+
{
|
|
6097
|
+
"alg": "SHA-256",
|
|
6098
|
+
"content": "7fe99dcd111bd4a644f126260fbb693c91b81d779b9e8b194482ccd9964b8ae8"
|
|
6099
|
+
}
|
|
6100
|
+
]
|
|
6101
|
+
},
|
|
6102
|
+
{
|
|
6103
|
+
"type": "file",
|
|
6104
|
+
"name": "dist/setup-memory-deps.js.map",
|
|
6105
|
+
"hashes": [
|
|
6106
|
+
{
|
|
6107
|
+
"alg": "SHA-256",
|
|
6108
|
+
"content": "463f7984bde099d63e2b64c4373255160fba321ae8e6524191b547fe2a52b8e0"
|
|
6109
|
+
}
|
|
6110
|
+
]
|
|
6111
|
+
},
|
|
6072
6112
|
{
|
|
6073
6113
|
"type": "file",
|
|
6074
6114
|
"name": "dist/setup.d.ts",
|
|
6075
6115
|
"hashes": [
|
|
6076
6116
|
{
|
|
6077
6117
|
"alg": "SHA-256",
|
|
6078
|
-
"content": "
|
|
6118
|
+
"content": "5bb08d77d90dfae60cfb117f0495cbe23739f03a209960a5292ed6680f214bee"
|
|
6079
6119
|
}
|
|
6080
6120
|
]
|
|
6081
6121
|
},
|
|
@@ -6085,7 +6125,7 @@
|
|
|
6085
6125
|
"hashes": [
|
|
6086
6126
|
{
|
|
6087
6127
|
"alg": "SHA-256",
|
|
6088
|
-
"content": "
|
|
6128
|
+
"content": "a1b4f19126ab5175e78ea536fc474e8edd7d827c6598fe2b45bc3878ee973fd6"
|
|
6089
6129
|
}
|
|
6090
6130
|
]
|
|
6091
6131
|
},
|
|
@@ -6095,7 +6135,7 @@
|
|
|
6095
6135
|
"hashes": [
|
|
6096
6136
|
{
|
|
6097
6137
|
"alg": "SHA-256",
|
|
6098
|
-
"content": "
|
|
6138
|
+
"content": "5eee98e8f377ae61f60197924941d41ba054c57d5c3b4d80216bd1a1c54f1eb7"
|
|
6099
6139
|
}
|
|
6100
6140
|
]
|
|
6101
6141
|
},
|
|
@@ -6105,7 +6145,7 @@
|
|
|
6105
6145
|
"hashes": [
|
|
6106
6146
|
{
|
|
6107
6147
|
"alg": "SHA-256",
|
|
6108
|
-
"content": "
|
|
6148
|
+
"content": "8b8c9428d6fcc874c64cc25e1d28046b96cecb3ff3e854eb941702876cf6e4a8"
|
|
6109
6149
|
}
|
|
6110
6150
|
]
|
|
6111
6151
|
},
|
|
@@ -6555,7 +6595,7 @@
|
|
|
6555
6595
|
"hashes": [
|
|
6556
6596
|
{
|
|
6557
6597
|
"alg": "SHA-256",
|
|
6558
|
-
"content": "
|
|
6598
|
+
"content": "765d542b7e66403c575b8b1e4fa4096bf82591e71ad4a35ce4ec44f0f82762b3"
|
|
6559
6599
|
}
|
|
6560
6600
|
]
|
|
6561
6601
|
},
|
|
@@ -6565,7 +6605,7 @@
|
|
|
6565
6605
|
"hashes": [
|
|
6566
6606
|
{
|
|
6567
6607
|
"alg": "SHA-256",
|
|
6568
|
-
"content": "
|
|
6608
|
+
"content": "cb5895f0585ef30f4582b674c96ea17b3fe4f77979945d4727ad1059e9d11696"
|
|
6569
6609
|
}
|
|
6570
6610
|
]
|
|
6571
6611
|
},
|
|
@@ -6575,7 +6615,7 @@
|
|
|
6575
6615
|
"hashes": [
|
|
6576
6616
|
{
|
|
6577
6617
|
"alg": "SHA-256",
|
|
6578
|
-
"content": "
|
|
6618
|
+
"content": "8cbeb2a7f0c8667febce4f608d3aec85f1b6a046514ed261523b71c06f9cef15"
|
|
6579
6619
|
}
|
|
6580
6620
|
]
|
|
6581
6621
|
},
|
|
@@ -6585,7 +6625,7 @@
|
|
|
6585
6625
|
"hashes": [
|
|
6586
6626
|
{
|
|
6587
6627
|
"alg": "SHA-256",
|
|
6588
|
-
"content": "
|
|
6628
|
+
"content": "2a3512f82b2ed24802645d0048d300655d7990bb33c7d534865ddd490be74d7d"
|
|
6589
6629
|
}
|
|
6590
6630
|
]
|
|
6591
6631
|
},
|
|
@@ -7235,7 +7275,7 @@
|
|
|
7235
7275
|
"hashes": [
|
|
7236
7276
|
{
|
|
7237
7277
|
"alg": "SHA-256",
|
|
7238
|
-
"content": "
|
|
7278
|
+
"content": "c71f53acd6db19925e99d580dd9e90a082173a7fd0882cb8fce5202bbb63ce6a"
|
|
7239
7279
|
}
|
|
7240
7280
|
]
|
|
7241
7281
|
},
|
|
@@ -7245,7 +7285,7 @@
|
|
|
7245
7285
|
"hashes": [
|
|
7246
7286
|
{
|
|
7247
7287
|
"alg": "SHA-256",
|
|
7248
|
-
"content": "
|
|
7288
|
+
"content": "a4a21c19d297256e4170c43f499df322ae25d633de0d11b19ef3e382accc2e4d"
|
|
7249
7289
|
}
|
|
7250
7290
|
]
|
|
7251
7291
|
},
|
|
@@ -7255,7 +7295,7 @@
|
|
|
7255
7295
|
"hashes": [
|
|
7256
7296
|
{
|
|
7257
7297
|
"alg": "SHA-256",
|
|
7258
|
-
"content": "
|
|
7298
|
+
"content": "1d16db0711bfb03c89bf04a1ca87c3f19620554ff56df6bb6c1797814d919b81"
|
|
7259
7299
|
}
|
|
7260
7300
|
]
|
|
7261
7301
|
},
|
|
@@ -7265,7 +7305,7 @@
|
|
|
7265
7305
|
"hashes": [
|
|
7266
7306
|
{
|
|
7267
7307
|
"alg": "SHA-256",
|
|
7268
|
-
"content": "
|
|
7308
|
+
"content": "fafeab618345a308eb1c32643bf6a740e122e281a69c4fa97d1040fcd6ad8396"
|
|
7269
7309
|
}
|
|
7270
7310
|
]
|
|
7271
7311
|
},
|
|
@@ -7595,7 +7635,7 @@
|
|
|
7595
7635
|
"hashes": [
|
|
7596
7636
|
{
|
|
7597
7637
|
"alg": "SHA-256",
|
|
7598
|
-
"content": "
|
|
7638
|
+
"content": "6b264b0c6100053392988e917714cb626666b13134052286f462080cfde7e992"
|
|
7599
7639
|
}
|
|
7600
7640
|
]
|
|
7601
7641
|
},
|
|
@@ -7605,7 +7645,7 @@
|
|
|
7605
7645
|
"hashes": [
|
|
7606
7646
|
{
|
|
7607
7647
|
"alg": "SHA-256",
|
|
7608
|
-
"content": "
|
|
7648
|
+
"content": "a9b6461415716a7fa2d4fc8e8465bfaf7b6ed2b580902a27f5dc89530d400b4c"
|
|
7609
7649
|
}
|
|
7610
7650
|
]
|
|
7611
7651
|
},
|
|
@@ -7615,7 +7655,7 @@
|
|
|
7615
7655
|
"hashes": [
|
|
7616
7656
|
{
|
|
7617
7657
|
"alg": "SHA-256",
|
|
7618
|
-
"content": "
|
|
7658
|
+
"content": "b39a7168fb7c07f6e8a5b4e8b3d6d5f40276b18eeac3d25019cf195e5bf7dc0d"
|
|
7619
7659
|
}
|
|
7620
7660
|
]
|
|
7621
7661
|
},
|
|
@@ -7625,7 +7665,7 @@
|
|
|
7625
7665
|
"hashes": [
|
|
7626
7666
|
{
|
|
7627
7667
|
"alg": "SHA-256",
|
|
7628
|
-
"content": "
|
|
7668
|
+
"content": "e97da7f04971b4771e2060b89fa3659cd4796ea9f92c03fe4eb5d1305398ef8e"
|
|
7629
7669
|
}
|
|
7630
7670
|
]
|
|
7631
7671
|
},
|
|
@@ -7635,7 +7675,7 @@
|
|
|
7635
7675
|
"hashes": [
|
|
7636
7676
|
{
|
|
7637
7677
|
"alg": "SHA-256",
|
|
7638
|
-
"content": "
|
|
7678
|
+
"content": "8460d23b0032130ab34bc9cfd7bcdfbe897a7c40b3ca03665bb1de519851c961"
|
|
7639
7679
|
}
|
|
7640
7680
|
]
|
|
7641
7681
|
},
|
|
@@ -7645,7 +7685,7 @@
|
|
|
7645
7685
|
"hashes": [
|
|
7646
7686
|
{
|
|
7647
7687
|
"alg": "SHA-256",
|
|
7648
|
-
"content": "
|
|
7688
|
+
"content": "d755ce82e6640ac232ad21006e2165fff690b38fe52f43ce98a0c64ed9b0e00d"
|
|
7649
7689
|
}
|
|
7650
7690
|
]
|
|
7651
7691
|
},
|
|
@@ -7655,7 +7695,7 @@
|
|
|
7655
7695
|
"hashes": [
|
|
7656
7696
|
{
|
|
7657
7697
|
"alg": "SHA-256",
|
|
7658
|
-
"content": "
|
|
7698
|
+
"content": "c594a2f15f0ee53ffee51c92dc7fb96ba276d192c7492ef9b5d3a62089524bb9"
|
|
7659
7699
|
}
|
|
7660
7700
|
]
|
|
7661
7701
|
},
|
|
@@ -7665,7 +7705,7 @@
|
|
|
7665
7705
|
"hashes": [
|
|
7666
7706
|
{
|
|
7667
7707
|
"alg": "SHA-256",
|
|
7668
|
-
"content": "
|
|
7708
|
+
"content": "7f5da97933113d32eaf6ef6735f39b2536dd1f3479f43439b7250789c3143d17"
|
|
7669
7709
|
}
|
|
7670
7710
|
]
|
|
7671
7711
|
},
|
|
@@ -7759,7 +7799,7 @@
|
|
|
7759
7799
|
},
|
|
7760
7800
|
{
|
|
7761
7801
|
"name": "dz:canonical-json-sha256-v2",
|
|
7762
|
-
"value": "
|
|
7802
|
+
"value": "c4f5afb2d6c68fe4fd7ba0cfec67e61ed72f39967fcccee82c16a9c1aac4f88a"
|
|
7763
7803
|
}
|
|
7764
7804
|
]
|
|
7765
7805
|
},
|
|
@@ -8979,7 +9019,7 @@
|
|
|
8979
9019
|
"hashes": [
|
|
8980
9020
|
{
|
|
8981
9021
|
"alg": "SHA-256",
|
|
8982
|
-
"content": "
|
|
9022
|
+
"content": "4903437dd0411b2379dff11823124a07001100334b986908c91f19b6671e5308"
|
|
8983
9023
|
}
|
|
8984
9024
|
]
|
|
8985
9025
|
},
|
|
@@ -9109,7 +9149,7 @@
|
|
|
9109
9149
|
"hashes": [
|
|
9110
9150
|
{
|
|
9111
9151
|
"alg": "SHA-256",
|
|
9112
|
-
"content": "
|
|
9152
|
+
"content": "b4fa02f244f59bfc02f69d3b9894e48b080bca5e30ae8dda6d695a09fb45705b"
|
|
9113
9153
|
}
|
|
9114
9154
|
]
|
|
9115
9155
|
},
|
|
@@ -9313,13 +9353,23 @@
|
|
|
9313
9353
|
}
|
|
9314
9354
|
]
|
|
9315
9355
|
},
|
|
9356
|
+
{
|
|
9357
|
+
"type": "file",
|
|
9358
|
+
"name": "src/setup-memory-deps.ts",
|
|
9359
|
+
"hashes": [
|
|
9360
|
+
{
|
|
9361
|
+
"alg": "SHA-256",
|
|
9362
|
+
"content": "ba01380f84272b0f3384f3902908b839d55ae2e787f9b4da7381a20a8ad1e4d7"
|
|
9363
|
+
}
|
|
9364
|
+
]
|
|
9365
|
+
},
|
|
9316
9366
|
{
|
|
9317
9367
|
"type": "file",
|
|
9318
9368
|
"name": "src/setup.ts",
|
|
9319
9369
|
"hashes": [
|
|
9320
9370
|
{
|
|
9321
9371
|
"alg": "SHA-256",
|
|
9322
|
-
"content": "
|
|
9372
|
+
"content": "bc10eae3bac47dcd387a9f2618df27e2e93a0eacf3809141a02484ebe1719121"
|
|
9323
9373
|
}
|
|
9324
9374
|
]
|
|
9325
9375
|
},
|
|
@@ -9449,7 +9499,7 @@
|
|
|
9449
9499
|
"hashes": [
|
|
9450
9500
|
{
|
|
9451
9501
|
"alg": "SHA-256",
|
|
9452
|
-
"content": "
|
|
9502
|
+
"content": "c6ed5f1b7f0ea3b5088c4f54a93360ca1455254cf76661535e0bef7b8f8cb2fc"
|
|
9453
9503
|
}
|
|
9454
9504
|
]
|
|
9455
9505
|
},
|
|
@@ -9619,7 +9669,7 @@
|
|
|
9619
9669
|
"hashes": [
|
|
9620
9670
|
{
|
|
9621
9671
|
"alg": "SHA-256",
|
|
9622
|
-
"content": "
|
|
9672
|
+
"content": "31b8bc15d0783461fb9d6d0ec9bb6f971f30dc830690410fa1cf0ee09c236222"
|
|
9623
9673
|
}
|
|
9624
9674
|
]
|
|
9625
9675
|
},
|
|
@@ -9709,7 +9759,7 @@
|
|
|
9709
9759
|
"hashes": [
|
|
9710
9760
|
{
|
|
9711
9761
|
"alg": "SHA-256",
|
|
9712
|
-
"content": "
|
|
9762
|
+
"content": "ac72cb4f5fa62cb9d135b1218896e5bec418415fbaffad4c885790e1db52104a"
|
|
9713
9763
|
}
|
|
9714
9764
|
]
|
|
9715
9765
|
},
|
|
@@ -9719,7 +9769,7 @@
|
|
|
9719
9769
|
"hashes": [
|
|
9720
9770
|
{
|
|
9721
9771
|
"alg": "SHA-256",
|
|
9722
|
-
"content": "
|
|
9772
|
+
"content": "c1ecd9dbe1fbcccd016a708656378d2701119644d4be2c815a24a6800d60b7be"
|
|
9723
9773
|
}
|
|
9724
9774
|
]
|
|
9725
9775
|
},
|
package/src/publish.ts
CHANGED
|
@@ -161,7 +161,7 @@ export interface PublishReport {
|
|
|
161
161
|
readonly skipped: number;
|
|
162
162
|
readonly errors: number;
|
|
163
163
|
readonly dryRun: boolean;
|
|
164
|
-
/** Repo-relative README paths whose first joint core/CLI release line was rewritten. */
|
|
164
|
+
/** Repo-relative README paths whose first explicitly marked joint core/CLI release line was rewritten. */
|
|
165
165
|
readonly releaseLineSynced: readonly string[];
|
|
166
166
|
readonly releaseLineReport: readonly ReleaseLineReport[];
|
|
167
167
|
/** Post-publication sync failures are warnings: registry-confirmed packages cannot be unpublished. */
|
|
@@ -677,8 +677,8 @@ function isInstallPinContext(line: string, tokenStart: number): boolean {
|
|
|
677
677
|
* bare "X" in a sentence) rewrote by default until someone thought to deny it too. An allowlist has
|
|
678
678
|
* no such gap: an unrecognised shape is history by default, not by enumeration.
|
|
679
679
|
*
|
|
680
|
-
* 1.
|
|
681
|
-
* `` `<name> vX` ``
|
|
680
|
+
* 1. an explicitly marked current release-line token — `` `harness-core vX` · `harness-cli vY` `` and any generalised
|
|
681
|
+
* `` `<name> vX` `` in its contiguous chain, including a trailing `` · `memory vZ` `` segment
|
|
682
682
|
* (release-line.ts `isReleaseLineToken`/`GENERIC_RELEASE_TOKEN_RE`).
|
|
683
683
|
* 2. a current-release FOOTER prefix (`FOOTER_STAMP_PREFIX_RE`) — position-aware, so only the
|
|
684
684
|
* token immediately after the label is allowed.
|
package/src/release-line.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { maskMarkdown } from './markdown-masker.js';
|
|
2
|
+
|
|
1
3
|
export const RELEASE_LINE_RE = /`harness-core v(\d+\.\d+\.\d+)` · `harness-cli v(\d+\.\d+\.\d+)`/;
|
|
2
4
|
|
|
3
5
|
export interface ReleaseLineToken {
|
|
@@ -22,8 +24,15 @@ export interface ReleaseLineMatch extends ReleaseLineParse {
|
|
|
22
24
|
|
|
23
25
|
export function findReleaseLine(text: string): ReleaseLineMatch | null {
|
|
24
26
|
const lines = text.split('\n');
|
|
27
|
+
// A closed leading opt-in is metadata, not an HTML example block. Blank only
|
|
28
|
+
// that exact marker before masking, retaining offsets and all enclosing blocks.
|
|
29
|
+
const maskInput = text.replace(/^ {0,3}<!-- dz:version -->/gm, (marker) => ' '.repeat(marker.length));
|
|
30
|
+
const visible = String(maskMarkdown(maskInput, { unclosed: 'hide' })).split('\n');
|
|
25
31
|
for (let index = 0; index < lines.length; index++) {
|
|
26
32
|
const line = lines[index]!;
|
|
33
|
+
// A joint pair is structural history until the author opts this physical line in.
|
|
34
|
+
// Masked examples cannot supply current metadata to the writer, report, or guard.
|
|
35
|
+
if (!line.includes('<!-- dz:version -->') || !RELEASE_LINE_RE.test(visible[index]!)) continue;
|
|
27
36
|
const parsed = parseReleaseLine(line);
|
|
28
37
|
if (parsed !== null) {
|
|
29
38
|
return { index, line, core: parsed.tokens[0]!.version, cli: parsed.tokens[1]!.version, ...parsed };
|
|
@@ -89,19 +98,8 @@ export function parseReleaseLine(line: string): ReleaseLineParse | null {
|
|
|
89
98
|
return { tokens, chainEnd, wrapped: /\s*·\s*$/.test(line.slice(chainEnd)) };
|
|
90
99
|
}
|
|
91
100
|
|
|
92
|
-
/**
|
|
93
|
-
* Is the OLD-VERSION occurrence at `[start, end)` in `line` sitting inside a `` `<name> vX` ``
|
|
94
|
-
* backtick token? A POSITIVE override for `planReadmeVersionSync`'s citation heuristic: a token
|
|
95
|
-
* this shape matches is a release-line stamp, never a historical citation, even where it sits next
|
|
96
|
-
* to punctuation ("/", "on ") the citation heuristic would otherwise read as a citation cue.
|
|
97
|
-
*/
|
|
101
|
+
/** A marked current joint chain grants token permission only through its structural boundary. */
|
|
98
102
|
export function isReleaseLineToken(line: string, start: number, end: number): boolean {
|
|
99
|
-
|
|
100
|
-
// the JOINT release-line shape (`RELEASE_LINE_RE`); an isolated `` `memory v0.8.25` `` in a
|
|
101
|
-
// historical sentence is history and must not move.
|
|
102
|
-
// Codex r3 HIGH (lead): the permission is the joint pair PLUS the CONTIGUOUS ` · `<name> vX``
|
|
103
|
-
// chain that follows it — not the whole line. `` `harness-core vX` · `harness-cli vY` — historically
|
|
104
|
-
// `memory vZ` `` moves the first two and keeps the third (prose broke the chain).
|
|
105
|
-
const p = parseReleaseLine(line);
|
|
103
|
+
const p = findReleaseLine(line);
|
|
106
104
|
return p !== null && p.tokens[0]!.start <= start && end <= p.chainEnd;
|
|
107
105
|
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/** Exact consumer npm persistence and local native readiness. No ancestor/global installs. */
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, rmSync, realpathSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { execFileSync } from 'node:child_process';
|
|
5
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
6
|
+
|
|
7
|
+
export const MEMORY_DEFAULTS = { agentdb: '3.0.0-alpha.20', 'better-sqlite3': '11.10.0' } as const;
|
|
8
|
+
const names = Object.keys(MEMORY_DEFAULTS) as (keyof typeof MEMORY_DEFAULTS)[];
|
|
9
|
+
const sections = ['dependencies', 'devDependencies', 'optionalDependencies'] as const;
|
|
10
|
+
type Json = Record<string, any>;
|
|
11
|
+
export interface MemoryDependencyResult {
|
|
12
|
+
readonly ready: boolean;
|
|
13
|
+
readonly changedManifest: boolean;
|
|
14
|
+
readonly changedLock: boolean;
|
|
15
|
+
readonly detail: string;
|
|
16
|
+
}
|
|
17
|
+
const object = (value: unknown): value is Json => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
18
|
+
const same = (a: unknown, b: unknown) => isDeepStrictEqual(a, b);
|
|
19
|
+
const bytes = (path: string) => existsSync(path) ? readFileSync(path, 'utf8') : null;
|
|
20
|
+
function json(path: string): Json {
|
|
21
|
+
const value: unknown = JSON.parse(readFileSync(path, 'utf8'));
|
|
22
|
+
if (!object(value)) throw Error(`${path}: expected a JSON object`);
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
export function supportedMemoryVersion(name: keyof typeof MEMORY_DEFAULTS, value: unknown): value is string {
|
|
26
|
+
const number = '(?:0|[1-9][0-9]*)';
|
|
27
|
+
return typeof value === 'string' && new RegExp(name === 'agentdb'
|
|
28
|
+
? `^(?:3\\.${number}\\.${number}|3\\.0\\.0-alpha\\.${number})$`
|
|
29
|
+
: `^11\\.${number}\\.${number}$`).test(value);
|
|
30
|
+
}
|
|
31
|
+
function installed(root: string, name: string): string | null {
|
|
32
|
+
const path = join(root, 'node_modules', name, 'package.json');
|
|
33
|
+
if (!existsSync(path)) return null;
|
|
34
|
+
const pkg = json(path);
|
|
35
|
+
if (pkg['name'] !== name || typeof pkg['version'] !== 'string') throw Error(`${name}: malformed installed package metadata`);
|
|
36
|
+
return pkg['version'];
|
|
37
|
+
}
|
|
38
|
+
function lockVersion(lock: Json | null, name: string): string | null {
|
|
39
|
+
const item = lock?.['packages']?.[`node_modules/${name}`] ?? lock?.['dependencies']?.[name];
|
|
40
|
+
return item?.version ?? null;
|
|
41
|
+
}
|
|
42
|
+
function selectVersions(root: string, pkg: Json, lock: Json | null): Record<string, string> {
|
|
43
|
+
for (const section of [...sections, 'peerDependencies']) {
|
|
44
|
+
if (pkg[section] !== undefined && !object(pkg[section])) throw Error(`package.json: malformed ${section}`);
|
|
45
|
+
}
|
|
46
|
+
const versions: Record<string, string> = {};
|
|
47
|
+
for (const name of names) {
|
|
48
|
+
if (Object.hasOwn(pkg['peerDependencies'] ?? {}, name)) throw Error(`${name}: peer declaration is outside exact persistence repair`);
|
|
49
|
+
const declared = sections.flatMap(section => Object.hasOwn(pkg[section] ?? {}, name) ? [pkg[section][name]] : []);
|
|
50
|
+
if (declared.some(value => !supportedMemoryVersion(name, value)) || new Set(declared).size > 1) throw Error(`${name}: conflicting or non-exact/unsupported saved declaration; original files preserved`);
|
|
51
|
+
if (declared.length) { versions[name] = declared[0]; continue; }
|
|
52
|
+
const local = installed(root, name), locked = lockVersion(lock, name);
|
|
53
|
+
if (local !== null) {
|
|
54
|
+
if (!supportedMemoryVersion(name, local)) throw Error(`${name}: unsupported installed-only version ${local}`);
|
|
55
|
+
if (locked !== null && locked !== local) throw Error(`${name}: installed-only and orphan lock versions conflict`);
|
|
56
|
+
versions[name] = local;
|
|
57
|
+
} else if (locked !== null) throw Error(`${name}: incomplete legacy lock-only state; original files preserved`);
|
|
58
|
+
else versions[name] = MEMORY_DEFAULTS[name];
|
|
59
|
+
}
|
|
60
|
+
return versions;
|
|
61
|
+
}
|
|
62
|
+
function persisted(pkg: Json, lock: Json | null, versions: Record<string, string>): boolean {
|
|
63
|
+
return names.every(name => pkg['devDependencies']?.[name] === versions[name]
|
|
64
|
+
&& !Object.hasOwn(pkg['dependencies'] ?? {}, name) && !Object.hasOwn(pkg['optionalDependencies'] ?? {}, name)
|
|
65
|
+
&& lockVersion(lock, name) === versions[name] && lock?.['packages']?.['']?.['devDependencies']?.[name] === versions[name]
|
|
66
|
+
&& !Object.hasOwn(lock?.['packages']?.['']?.['dependencies'] ?? {}, name)
|
|
67
|
+
&& !Object.hasOwn(lock?.['packages']?.['']?.['optionalDependencies'] ?? {}, name));
|
|
68
|
+
}
|
|
69
|
+
function protectedManifest(pkg: Json): Json {
|
|
70
|
+
const copy: Json = JSON.parse(JSON.stringify(pkg));
|
|
71
|
+
for (const section of sections) {
|
|
72
|
+
if (!object(copy[section])) continue;
|
|
73
|
+
for (const name of names) delete copy[section][name];
|
|
74
|
+
if (!Object.keys(copy[section]).length) delete copy[section];
|
|
75
|
+
}
|
|
76
|
+
return copy;
|
|
77
|
+
}
|
|
78
|
+
function resolutions(lock: Json | null): Record<string, string> {
|
|
79
|
+
const result: Record<string, string> = {};
|
|
80
|
+
if (object(lock?.['packages'])) for (const [path, item] of Object.entries(lock['packages'])) {
|
|
81
|
+
if (path && !names.some(name => path === `node_modules/${name}`) && object(item) && typeof item['version'] === 'string') result[path] = item['version'];
|
|
82
|
+
}
|
|
83
|
+
else if (object(lock?.['dependencies'])) for (const [name, item] of Object.entries(lock['dependencies'])) {
|
|
84
|
+
if (!names.includes(name as keyof typeof MEMORY_DEFAULTS) && object(item) && typeof item['version'] === 'string') result[`node_modules/${name}`] = item['version'];
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function npm(root: string, args: string[]): void {
|
|
89
|
+
execFileSync(process.platform === 'win32' ? 'npm.cmd' : 'npm', args, {
|
|
90
|
+
cwd: root, timeout: 300000, maxBuffer: 8 * 1024 * 1024, stdio: 'pipe', shell: process.platform === 'win32',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
export function probeMemoryNative(root: string): string | null {
|
|
94
|
+
try {
|
|
95
|
+
for (const name of names) if (installed(root, name) === null) return `${name}: local package missing`;
|
|
96
|
+
const script = `const {createRequire}=require('node:module'),fs=require('node:fs'),path=require('node:path');
|
|
97
|
+
const root=process.argv[1],r=createRequire(path.join(root,'package.json')),local=fs.realpathSync(path.join(root,'node_modules'));
|
|
98
|
+
const resolved=fs.realpathSync(r.resolve('better-sqlite3')); if(path.relative(local,resolved).startsWith('..'))throw Error('native module resolved outside project');
|
|
99
|
+
const Sqlite=r('better-sqlite3'),db=new Sqlite(':memory:');try{if(db.prepare('SELECT 42 AS answer').get().answer!==42)throw Error('native SELECT failed');}finally{db.close();}
|
|
100
|
+
process.stdout.write('native-sql-ready');`;
|
|
101
|
+
const output = execFileSync(process.execPath, ['-e', script, realpathSync(root)], { cwd: root, timeout: 60000, maxBuffer: 4 * 1024 * 1024, stdio: 'pipe', encoding: 'utf8' });
|
|
102
|
+
return output === 'native-sql-ready' ? null : 'native SQL readiness stdout not established';
|
|
103
|
+
} catch (error) { return `native SQLite unavailable: ${error instanceof Error ? error.message : String(error)}`; }
|
|
104
|
+
}
|
|
105
|
+
export function reconcileMemoryDependencies(projectRoot: string, repair = true): MemoryDependencyResult {
|
|
106
|
+
const pkgPath = join(projectRoot, 'package.json'), lockPath = join(projectRoot, 'package-lock.json');
|
|
107
|
+
const beforePkg = bytes(pkgPath), beforeLock = bytes(lockPath);
|
|
108
|
+
let stage = 'validate', repaired = false;
|
|
109
|
+
const result = (ready: boolean, detail: string): MemoryDependencyResult => ({ ready, changedManifest: bytes(pkgPath) !== beforePkg, changedLock: bytes(lockPath) !== beforeLock, detail });
|
|
110
|
+
try {
|
|
111
|
+
const pkg = beforePkg === null ? { name: 'dz-harness-project', private: true, version: '0.0.0' } : json(pkgPath);
|
|
112
|
+
const lock = beforeLock === null ? null : json(lockPath);
|
|
113
|
+
const versions = selectVersions(projectRoot, pkg, lock);
|
|
114
|
+
const localCurrent = names.every(name => installed(projectRoot, name) === versions[name]);
|
|
115
|
+
const savedCurrent = persisted(pkg, lock, versions);
|
|
116
|
+
if (!repair && (!savedCurrent || !localCurrent)) return result(false, 'saved/local dependency state is inconsistent; run setup to repair exact devDependencies');
|
|
117
|
+
const nativeBefore = localCurrent ? probeMemoryNative(projectRoot) : 'local package versions need repair';
|
|
118
|
+
if (!repair && nativeBefore) return result(false, nativeBefore);
|
|
119
|
+
if (!savedCurrent || !localCurrent) {
|
|
120
|
+
stage = 'npm persistence repair';
|
|
121
|
+
const protectedFields = protectedManifest(pkg), protectedLock = resolutions(lock);
|
|
122
|
+
try {
|
|
123
|
+
// npm can retain an existing optional declaration despite --save-dev. Selection and
|
|
124
|
+
// conflicts were validated above; normalize ONLY the two memory declarations first.
|
|
125
|
+
const canonical: Json = JSON.parse(JSON.stringify(pkg));
|
|
126
|
+
for (const section of sections) {
|
|
127
|
+
if (!object(canonical[section])) continue;
|
|
128
|
+
let removed = false;
|
|
129
|
+
for (const name of names) if (Object.hasOwn(canonical[section], name)) { delete canonical[section][name]; removed = true; }
|
|
130
|
+
if (removed && !Object.keys(canonical[section]).length) delete canonical[section];
|
|
131
|
+
}
|
|
132
|
+
canonical['devDependencies'] = { ...(canonical['devDependencies'] ?? {}), ...versions };
|
|
133
|
+
if (beforePkg === null || !same(canonical, pkg)) writeFileSync(pkgPath, JSON.stringify(canonical, null, 2) + '\n');
|
|
134
|
+
npm(projectRoot, ['install', ...names.map(name => `${name}@${versions[name]}`), '--save-dev', '--save-exact', '--no-audit', '--no-fund', '--loglevel=error']);
|
|
135
|
+
const after = json(pkgPath), afterLock = json(lockPath), afterResolutions = resolutions(afterLock);
|
|
136
|
+
if (!same(protectedManifest(after), protectedFields) || Object.entries(protectedLock).some(([path, version]) => afterResolutions[path] !== version)) {
|
|
137
|
+
throw Error('npm changed protected unrelated manifest fields/lock resolutions');
|
|
138
|
+
}
|
|
139
|
+
if (!persisted(after, afterLock, versions) || !names.every(name => installed(projectRoot, name) === versions[name])) throw Error('npm did not establish requested exact manifest/lock/local versions');
|
|
140
|
+
repaired = true;
|
|
141
|
+
} catch (error) {
|
|
142
|
+
// npm is not a whole-project transaction. Restore only protected manifest/lock files.
|
|
143
|
+
let changedProtected = false;
|
|
144
|
+
try {
|
|
145
|
+
const after = existsSync(pkgPath) ? json(pkgPath) : {};
|
|
146
|
+
const afterResolutions = resolutions(existsSync(lockPath) ? json(lockPath) : null);
|
|
147
|
+
changedProtected = !same(protectedManifest(after), protectedFields) || Object.entries(protectedLock).some(([path, version]) => afterResolutions[path] !== version);
|
|
148
|
+
} catch { changedProtected = true; }
|
|
149
|
+
if (changedProtected) {
|
|
150
|
+
if (beforePkg === null) rmSync(pkgPath, { force: true }); else writeFileSync(pkgPath, beforePkg);
|
|
151
|
+
if (beforeLock === null) rmSync(lockPath, { force: true }); else writeFileSync(lockPath, beforeLock);
|
|
152
|
+
throw Error(`protected manifest/lock restored after npm changed unrelated state; local modules may be incomplete: ${String(error)}`);
|
|
153
|
+
}
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
} else if (repair && nativeBefore) {
|
|
157
|
+
stage = 'native rebuild'; npm(projectRoot, ['rebuild', 'better-sqlite3', '--no-audit', '--no-fund', '--loglevel=error']); repaired = true;
|
|
158
|
+
}
|
|
159
|
+
stage = 'native SQL probe';
|
|
160
|
+
const nativeError = probeMemoryNative(projectRoot);
|
|
161
|
+
if (nativeError) return result(false, `INCOMPLETE ${stage}: ${nativeError}; package.json ${bytes(pkgPath) === beforePkg ? 'unchanged' : 'changed'}, package-lock.json ${bytes(lockPath) === beforeLock ? 'unchanged' : 'changed'}`);
|
|
162
|
+
return result(true, `${repaired ? 'repaired exact devDependencies/local readiness' : 'already current exact devDependencies and native SQLite'}; package.json ${bytes(pkgPath) === beforePkg ? 'unchanged' : 'changed'}, package-lock.json ${bytes(lockPath) === beforeLock ? 'unchanged' : 'changed'}; ${names.map(name => `${name}@${versions[name]}`).join(', ')}; native SELECT 42 passed`);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return result(false, `INCOMPLETE ${stage}: ${error instanceof Error ? error.message : String(error)}; package.json ${bytes(pkgPath) === beforePkg ? 'unchanged' : 'changed'}, package-lock.json ${bytes(lockPath) === beforeLock ? 'unchanged' : 'changed'}`);
|
|
165
|
+
}
|
|
166
|
+
}
|