@bongos/core 1.19.316 → 1.19.318
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/.bongos-core.json +108 -33
- package/modules/economy/cost.js +84 -19
- package/modules/lifecycle/db-analytics.js +719 -0
- package/modules/lifecycle/db-claim-reads.js +165 -0
- package/modules/lifecycle/db-claims.js +934 -0
- package/modules/lifecycle/db-deps-criteria.js +441 -0
- package/modules/lifecycle/db-goals.js +763 -0
- package/modules/lifecycle/db-grade.js +233 -0
- package/modules/lifecycle/db-overrides.js +181 -0
- package/modules/lifecycle/db-rank-authz.js +446 -0
- package/modules/lifecycle/db-shared.js +115 -0
- package/modules/lifecycle/db-ship.js +994 -0
- package/modules/lifecycle/db-tasks.js +810 -0
- package/modules/lifecycle/db-versions.js +118 -0
- package/modules/lifecycle/db.js +167 -5564
- package/modules/lifecycle/publish-reconciler.js +7 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/scripts/gds/coreB-carve-proof.sh +18 -9
- package/scripts/gds/fitness.js +34 -26
- package/scripts/gds/identity-strip.js +75 -0
- package/scripts/gds/provision.js +7 -3
- package/scripts/gds/run-unit-tests.js +8 -1
- package/scripts/gds/session-cost.js +16 -0
- package/scripts/gds/session-digest-build.js +261 -0
- package/scripts/gds/ship.js +7 -198
- package/src/module-api.js +5 -1
- package/tests/auto_satisfy_criteria.mjs +3 -2
- package/tests/dependencies_migration.mjs +3 -2
- package/tests/fitness.mjs +43 -0
- package/tests/goal_abuse_matrix.mjs +3 -2
- package/tests/goal_advisory.mjs +3 -2
- package/tests/government_claim_eligibility.mjs +3 -1
- package/tests/government_rank_sync.mjs +9 -2
- package/tests/helpers.mjs +19 -0
- package/tests/migration_allocation.mjs +3 -1
- package/tests/publish_reconciler.mjs +41 -1
- package/tests/rank_gate.mjs +3 -1
- package/tests/reward_gate.mjs +3 -1
- package/tests/session_cost.mjs +64 -0
- package/tests/session_cost_row_raise.mjs +139 -0
- package/tests/session_records.mjs +72 -0
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.318",
|
|
6
|
+
"core_contract": "1.19.318",
|
|
7
|
+
"source_commit": "01d0a25617f7ca9212b310552724d7eb8c183a32",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-23T22:
|
|
9
|
+
"built_at": "2026-08-23T22:11:19.148Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 323,
|
|
13
13
|
"agent_docs_stubbed": 22,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 1438,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 1783,
|
|
20
|
+
"tree_sha256": "24fa1a6a45d9a8ad89550dcdf06b82e5aeffa56776dcd6666a1be6524d9d4a6e",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -2987,7 +2987,7 @@
|
|
|
2987
2987
|
{
|
|
2988
2988
|
"path": "modules/economy/cost.js",
|
|
2989
2989
|
"mode": "0000644",
|
|
2990
|
-
"sha256": "
|
|
2990
|
+
"sha256": "01bc7725fe16388971fd4def2544d0de9af6b3a522973df7ef86386737933d40"
|
|
2991
2991
|
},
|
|
2992
2992
|
{
|
|
2993
2993
|
"path": "modules/economy/credits.js",
|
|
@@ -3824,10 +3824,70 @@
|
|
|
3824
3824
|
"mode": "0000644",
|
|
3825
3825
|
"sha256": "4a4a513ed0759e1e999454e6b6972b921789a5c2a88521755812d97fb6194f83"
|
|
3826
3826
|
},
|
|
3827
|
+
{
|
|
3828
|
+
"path": "modules/lifecycle/db-analytics.js",
|
|
3829
|
+
"mode": "0000644",
|
|
3830
|
+
"sha256": "b0cb5fb6853d39fd99feaa0b8e3b1040b0877a8476273789dad8976be42070cd"
|
|
3831
|
+
},
|
|
3832
|
+
{
|
|
3833
|
+
"path": "modules/lifecycle/db-claim-reads.js",
|
|
3834
|
+
"mode": "0000644",
|
|
3835
|
+
"sha256": "7aafa6f538811bd29d7f8ce3ebbf59fea72a90fea99de1fdfb6c62124eff23d5"
|
|
3836
|
+
},
|
|
3837
|
+
{
|
|
3838
|
+
"path": "modules/lifecycle/db-claims.js",
|
|
3839
|
+
"mode": "0000644",
|
|
3840
|
+
"sha256": "dbce7de39b91cdd1843ba26efc3f3be76690a7112aaa3b1b0406a9b9f98dfb32"
|
|
3841
|
+
},
|
|
3842
|
+
{
|
|
3843
|
+
"path": "modules/lifecycle/db-deps-criteria.js",
|
|
3844
|
+
"mode": "0000644",
|
|
3845
|
+
"sha256": "b3906a4704be5df9cdfdff9f13e2a18878f93ff7285c42edf25856ec1c4531be"
|
|
3846
|
+
},
|
|
3847
|
+
{
|
|
3848
|
+
"path": "modules/lifecycle/db-goals.js",
|
|
3849
|
+
"mode": "0000644",
|
|
3850
|
+
"sha256": "29b950000d31618de168c6128d9b78c03daad7e68b9a9b6d3e83aa40abd3d9fb"
|
|
3851
|
+
},
|
|
3852
|
+
{
|
|
3853
|
+
"path": "modules/lifecycle/db-grade.js",
|
|
3854
|
+
"mode": "0000644",
|
|
3855
|
+
"sha256": "e6c9a996c11a73847317db47620007c8d21f70b19c73ade4499361c1c0c330f9"
|
|
3856
|
+
},
|
|
3857
|
+
{
|
|
3858
|
+
"path": "modules/lifecycle/db-overrides.js",
|
|
3859
|
+
"mode": "0000644",
|
|
3860
|
+
"sha256": "fa3f251ef2bd0d2caaf49ecc2a250ca65ea7814ee25d606e00c23db0572b23fe"
|
|
3861
|
+
},
|
|
3862
|
+
{
|
|
3863
|
+
"path": "modules/lifecycle/db-rank-authz.js",
|
|
3864
|
+
"mode": "0000644",
|
|
3865
|
+
"sha256": "c93780ea71bb2f8f3d2b21f042c21d029f1ed5336a3aaf178fb3e14925dcc19b"
|
|
3866
|
+
},
|
|
3867
|
+
{
|
|
3868
|
+
"path": "modules/lifecycle/db-shared.js",
|
|
3869
|
+
"mode": "0000644",
|
|
3870
|
+
"sha256": "17a6ddfb4a9415c67dfbd06b052a3a7686df7a55287aa78ff2b55c6a2ca3d954"
|
|
3871
|
+
},
|
|
3872
|
+
{
|
|
3873
|
+
"path": "modules/lifecycle/db-ship.js",
|
|
3874
|
+
"mode": "0000644",
|
|
3875
|
+
"sha256": "0a313d9c20cc0da5952e3a5acbca83cd1fd3df7ecccbbd109701d865b4dd2fe6"
|
|
3876
|
+
},
|
|
3877
|
+
{
|
|
3878
|
+
"path": "modules/lifecycle/db-tasks.js",
|
|
3879
|
+
"mode": "0000644",
|
|
3880
|
+
"sha256": "43748950aee899125bc40b8fb6f26a7df5645746e23fcbe6bbe3ea486f0b7248"
|
|
3881
|
+
},
|
|
3882
|
+
{
|
|
3883
|
+
"path": "modules/lifecycle/db-versions.js",
|
|
3884
|
+
"mode": "0000644",
|
|
3885
|
+
"sha256": "aa98bd22cf237579b065a9a85cb64dda30a0b6b9894ebc5d6ca0592bbb7a977f"
|
|
3886
|
+
},
|
|
3827
3887
|
{
|
|
3828
3888
|
"path": "modules/lifecycle/db.js",
|
|
3829
3889
|
"mode": "0000644",
|
|
3830
|
-
"sha256": "
|
|
3890
|
+
"sha256": "70448ebd079d5167bcf0c9c2b4473d46e996a54202f09f5a8ebc30980aba4166"
|
|
3831
3891
|
},
|
|
3832
3892
|
{
|
|
3833
3893
|
"path": "modules/lifecycle/dead-deps.js",
|
|
@@ -3912,7 +3972,7 @@
|
|
|
3912
3972
|
{
|
|
3913
3973
|
"path": "modules/lifecycle/publish-reconciler.js",
|
|
3914
3974
|
"mode": "0000644",
|
|
3915
|
-
"sha256": "
|
|
3975
|
+
"sha256": "28c61d55fe2b492f0fce4c99b60e88f0cbeb542c47c04482558818d65628e0d7"
|
|
3916
3976
|
},
|
|
3917
3977
|
{
|
|
3918
3978
|
"path": "modules/lifecycle/routes/analytics.js",
|
|
@@ -4582,12 +4642,12 @@
|
|
|
4582
4642
|
{
|
|
4583
4643
|
"path": "package-lock.json",
|
|
4584
4644
|
"mode": "0000644",
|
|
4585
|
-
"sha256": "
|
|
4645
|
+
"sha256": "509e4a76d5eb6f21fd8c926c6bf7ec9f1938d62ed4055558e2d3911858166b38"
|
|
4586
4646
|
},
|
|
4587
4647
|
{
|
|
4588
4648
|
"path": "package.json",
|
|
4589
4649
|
"mode": "0000644",
|
|
4590
|
-
"sha256": "
|
|
4650
|
+
"sha256": "5e3c53bb9627f4dcf747e5e7bc8fa7fb0e136554f04d96081137ca1bc05654ad"
|
|
4591
4651
|
},
|
|
4592
4652
|
{
|
|
4593
4653
|
"path": "public-docs/index.html",
|
|
@@ -5122,7 +5182,7 @@
|
|
|
5122
5182
|
{
|
|
5123
5183
|
"path": "scripts/gds/coreB-carve-proof.sh",
|
|
5124
5184
|
"mode": "0000644",
|
|
5125
|
-
"sha256": "
|
|
5185
|
+
"sha256": "55ac5440a1c5481766198d6a89cef601fde816024b592b1e77f535c465a2df47"
|
|
5126
5186
|
},
|
|
5127
5187
|
{
|
|
5128
5188
|
"path": "scripts/gds/cost.js",
|
|
@@ -5237,7 +5297,7 @@
|
|
|
5237
5297
|
{
|
|
5238
5298
|
"path": "scripts/gds/fitness.js",
|
|
5239
5299
|
"mode": "0000644",
|
|
5240
|
-
"sha256": "
|
|
5300
|
+
"sha256": "fc4af6845de5bf3775629d492bb793f96cf707dfd9837e338cb2344250f733b5"
|
|
5241
5301
|
},
|
|
5242
5302
|
{
|
|
5243
5303
|
"path": "scripts/gds/gate-review.js",
|
|
@@ -5339,6 +5399,11 @@
|
|
|
5339
5399
|
"mode": "0000644",
|
|
5340
5400
|
"sha256": "4bf1e6c352e83a63a4747b892c5f9310dc860f8b2f5fc7c607ed432dcb2dd110"
|
|
5341
5401
|
},
|
|
5402
|
+
{
|
|
5403
|
+
"path": "scripts/gds/identity-strip.js",
|
|
5404
|
+
"mode": "0000644",
|
|
5405
|
+
"sha256": "a5ac6e41f30fd13738e52800616c2e0e3b1f8150dbb5e3f43e1fdbced5f58fe0"
|
|
5406
|
+
},
|
|
5342
5407
|
{
|
|
5343
5408
|
"path": "scripts/gds/init.js",
|
|
5344
5409
|
"mode": "0000644",
|
|
@@ -5532,7 +5597,7 @@
|
|
|
5532
5597
|
{
|
|
5533
5598
|
"path": "scripts/gds/provision.js",
|
|
5534
5599
|
"mode": "0000644",
|
|
5535
|
-
"sha256": "
|
|
5600
|
+
"sha256": "b445702caa082164d8b733a44be2407f3e3889f28838dfd38222a6a0eb5ec672"
|
|
5536
5601
|
},
|
|
5537
5602
|
{
|
|
5538
5603
|
"path": "scripts/gds/publish-credential-check.js",
|
|
@@ -5607,7 +5672,7 @@
|
|
|
5607
5672
|
{
|
|
5608
5673
|
"path": "scripts/gds/run-unit-tests.js",
|
|
5609
5674
|
"mode": "0000644",
|
|
5610
|
-
"sha256": "
|
|
5675
|
+
"sha256": "c96e50e533f4e20dba91c6a26ac6efd2c6ad33ffcdc856eeb46af21a17e67975"
|
|
5611
5676
|
},
|
|
5612
5677
|
{
|
|
5613
5678
|
"path": "scripts/gds/sandbox-stage.js",
|
|
@@ -5767,7 +5832,12 @@
|
|
|
5767
5832
|
{
|
|
5768
5833
|
"path": "scripts/gds/session-cost.js",
|
|
5769
5834
|
"mode": "0000644",
|
|
5770
|
-
"sha256": "
|
|
5835
|
+
"sha256": "fdf3b9d8e0089078da550ac65d0c012583cc21103a668deecf481383a73c9da1"
|
|
5836
|
+
},
|
|
5837
|
+
{
|
|
5838
|
+
"path": "scripts/gds/session-digest-build.js",
|
|
5839
|
+
"mode": "0000644",
|
|
5840
|
+
"sha256": "95e5c21533f67588fd02fae311cef8985d3eee58ad3217fcb6e9998e1f4da965"
|
|
5771
5841
|
},
|
|
5772
5842
|
{
|
|
5773
5843
|
"path": "scripts/gds/session-digest.js",
|
|
@@ -5802,7 +5872,7 @@
|
|
|
5802
5872
|
{
|
|
5803
5873
|
"path": "scripts/gds/ship.js",
|
|
5804
5874
|
"mode": "0000644",
|
|
5805
|
-
"sha256": "
|
|
5875
|
+
"sha256": "8f2c0ca63abae081cccfa96059ae07b008bd108f85866a248075cb4a1b7e025e"
|
|
5806
5876
|
},
|
|
5807
5877
|
{
|
|
5808
5878
|
"path": "scripts/gds/skill-preflight.js",
|
|
@@ -6262,7 +6332,7 @@
|
|
|
6262
6332
|
{
|
|
6263
6333
|
"path": "src/module-api.js",
|
|
6264
6334
|
"mode": "0000644",
|
|
6265
|
-
"sha256": "
|
|
6335
|
+
"sha256": "af9d10cbaf1d6320df892f4d0e1403c0f5f1bb6e8c314695e89477690ba7fc85"
|
|
6266
6336
|
},
|
|
6267
6337
|
{
|
|
6268
6338
|
"path": "src/module-loader/catalog.js",
|
|
@@ -6492,7 +6562,7 @@
|
|
|
6492
6562
|
{
|
|
6493
6563
|
"path": "tests/auto_satisfy_criteria.mjs",
|
|
6494
6564
|
"mode": "0000644",
|
|
6495
|
-
"sha256": "
|
|
6565
|
+
"sha256": "135d0af6b1535e50d68ed62baa36b616ba28888e899940cabf2f2940f3cd6f9d"
|
|
6496
6566
|
},
|
|
6497
6567
|
{
|
|
6498
6568
|
"path": "tests/autonomous_fit_protected_paths.mjs",
|
|
@@ -6902,7 +6972,7 @@
|
|
|
6902
6972
|
{
|
|
6903
6973
|
"path": "tests/dependencies_migration.mjs",
|
|
6904
6974
|
"mode": "0000644",
|
|
6905
|
-
"sha256": "
|
|
6975
|
+
"sha256": "daf81be50910d712cdfe10ac2c50578f70dc1d8cf261d435db23a120ec310968"
|
|
6906
6976
|
},
|
|
6907
6977
|
{
|
|
6908
6978
|
"path": "tests/dependencies_polymorphic.mjs",
|
|
@@ -7112,7 +7182,7 @@
|
|
|
7112
7182
|
{
|
|
7113
7183
|
"path": "tests/fitness.mjs",
|
|
7114
7184
|
"mode": "0000644",
|
|
7115
|
-
"sha256": "
|
|
7185
|
+
"sha256": "465c7ef58342b6e03947858fe34649f5a13a5bcf3658478601baed1e8b2420ef"
|
|
7116
7186
|
},
|
|
7117
7187
|
{
|
|
7118
7188
|
"path": "tests/fitness_ratchets.mjs",
|
|
@@ -7192,7 +7262,7 @@
|
|
|
7192
7262
|
{
|
|
7193
7263
|
"path": "tests/goal_abuse_matrix.mjs",
|
|
7194
7264
|
"mode": "0000644",
|
|
7195
|
-
"sha256": "
|
|
7265
|
+
"sha256": "b9fea609f0dc0aa1c0d05c1794290a65e48996c817a4a435098e91220ade89c1"
|
|
7196
7266
|
},
|
|
7197
7267
|
{
|
|
7198
7268
|
"path": "tests/goal_achievement.mjs",
|
|
@@ -7202,7 +7272,7 @@
|
|
|
7202
7272
|
{
|
|
7203
7273
|
"path": "tests/goal_advisory.mjs",
|
|
7204
7274
|
"mode": "0000644",
|
|
7205
|
-
"sha256": "
|
|
7275
|
+
"sha256": "b9fe4a36c7b60512c71e1d4837e8639381d441c19261007e186cb8c369d5b2c6"
|
|
7206
7276
|
},
|
|
7207
7277
|
{
|
|
7208
7278
|
"path": "tests/goal_cli.mjs",
|
|
@@ -7332,7 +7402,7 @@
|
|
|
7332
7402
|
{
|
|
7333
7403
|
"path": "tests/government_claim_eligibility.mjs",
|
|
7334
7404
|
"mode": "0000644",
|
|
7335
|
-
"sha256": "
|
|
7405
|
+
"sha256": "7eb103c6a201345728af5002aae1be09c1f3b1459b74bef7ea14e990a28dd05b"
|
|
7336
7406
|
},
|
|
7337
7407
|
{
|
|
7338
7408
|
"path": "tests/government_config.mjs",
|
|
@@ -7392,7 +7462,7 @@
|
|
|
7392
7462
|
{
|
|
7393
7463
|
"path": "tests/government_rank_sync.mjs",
|
|
7394
7464
|
"mode": "0000644",
|
|
7395
|
-
"sha256": "
|
|
7465
|
+
"sha256": "8750d0bbfc33403ff451b780935496a037dbab4a8e30bdc089abde8da8b7400a"
|
|
7396
7466
|
},
|
|
7397
7467
|
{
|
|
7398
7468
|
"path": "tests/government_require_permission.mjs",
|
|
@@ -7532,7 +7602,7 @@
|
|
|
7532
7602
|
{
|
|
7533
7603
|
"path": "tests/helpers.mjs",
|
|
7534
7604
|
"mode": "0000644",
|
|
7535
|
-
"sha256": "
|
|
7605
|
+
"sha256": "7a306648d5fd083313126ce98d364e19d130313edf7d37dd23e3767c7e527c8f"
|
|
7536
7606
|
},
|
|
7537
7607
|
{
|
|
7538
7608
|
"path": "tests/hierarchy-config.mjs",
|
|
@@ -7847,7 +7917,7 @@
|
|
|
7847
7917
|
{
|
|
7848
7918
|
"path": "tests/migration_allocation.mjs",
|
|
7849
7919
|
"mode": "0000644",
|
|
7850
|
-
"sha256": "
|
|
7920
|
+
"sha256": "017770d7639ca5dfb204b613b9ed287fb01c1f768c4f6e0550cc0ac7cad5fb5e"
|
|
7851
7921
|
},
|
|
7852
7922
|
{
|
|
7853
7923
|
"path": "tests/migration_namespace.mjs",
|
|
@@ -8222,12 +8292,12 @@
|
|
|
8222
8292
|
{
|
|
8223
8293
|
"path": "tests/publish_reconciler.mjs",
|
|
8224
8294
|
"mode": "0000644",
|
|
8225
|
-
"sha256": "
|
|
8295
|
+
"sha256": "5a9ea0bf7b4d776a6f9036b8bd060fef76335533274ed748e9b9d742da6960d3"
|
|
8226
8296
|
},
|
|
8227
8297
|
{
|
|
8228
8298
|
"path": "tests/rank_gate.mjs",
|
|
8229
8299
|
"mode": "0000644",
|
|
8230
|
-
"sha256": "
|
|
8300
|
+
"sha256": "d8fff57f5fee95bf11a5c1df3e2c0e342d39ef5b22c5e87f47a61dd9a3d2a8cb"
|
|
8231
8301
|
},
|
|
8232
8302
|
{
|
|
8233
8303
|
"path": "tests/rank_tier_single_source.mjs",
|
|
@@ -8292,7 +8362,7 @@
|
|
|
8292
8362
|
{
|
|
8293
8363
|
"path": "tests/reward_gate.mjs",
|
|
8294
8364
|
"mode": "0000644",
|
|
8295
|
-
"sha256": "
|
|
8365
|
+
"sha256": "52f9997d60ce03c60137376dc2bba1940c669617f0ca69fdafd3d90091411df3"
|
|
8296
8366
|
},
|
|
8297
8367
|
{
|
|
8298
8368
|
"path": "tests/reward_mode_cost_plus_only.mjs",
|
|
@@ -8442,7 +8512,12 @@
|
|
|
8442
8512
|
{
|
|
8443
8513
|
"path": "tests/session_cost.mjs",
|
|
8444
8514
|
"mode": "0000644",
|
|
8445
|
-
"sha256": "
|
|
8515
|
+
"sha256": "5f330f79eee8c39dc589d892ba5fa6835906e7b61ff5fe52aec3285721e84876"
|
|
8516
|
+
},
|
|
8517
|
+
{
|
|
8518
|
+
"path": "tests/session_cost_row_raise.mjs",
|
|
8519
|
+
"mode": "0000644",
|
|
8520
|
+
"sha256": "74a106432222df7d8e845ec409bd2e1d49aff18bf80cdeff032cfe91b1d6dc3f"
|
|
8446
8521
|
},
|
|
8447
8522
|
{
|
|
8448
8523
|
"path": "tests/session_digest.mjs",
|
|
@@ -8462,7 +8537,7 @@
|
|
|
8462
8537
|
{
|
|
8463
8538
|
"path": "tests/session_records.mjs",
|
|
8464
8539
|
"mode": "0000644",
|
|
8465
|
-
"sha256": "
|
|
8540
|
+
"sha256": "8c62fe0bec07aea4c30f84d296eb7b40c9550606aacf6cb63f9644ca34f12069"
|
|
8466
8541
|
},
|
|
8467
8542
|
{
|
|
8468
8543
|
"path": "tests/session_reward_on_land.mjs",
|
package/modules/economy/cost.js
CHANGED
|
@@ -105,23 +105,51 @@ async function logCost({
|
|
|
105
105
|
outputUsd = null,
|
|
106
106
|
// task #385 / migration 181: which skill invocation incurred this cost.
|
|
107
107
|
skillName = null,
|
|
108
|
+
// task 1003217 — opt-in MONOTONIC RAISE on (source, source_ref) conflict.
|
|
109
|
+
//
|
|
110
|
+
// Default false, so every existing caller keeps the plain insert-once
|
|
111
|
+
// idempotency it relies on. The session reconciler below sets it true: a
|
|
112
|
+
// long session's digest GROWS on every ship, and a cost row written from an
|
|
113
|
+
// early digest must be allowed to catch up, or the session is billed at its
|
|
114
|
+
// first hour forever (the bug this task fixes).
|
|
115
|
+
//
|
|
116
|
+
// Safe because the update SETS an absolute amount rather than adding to one:
|
|
117
|
+
// re-running with the same figure is a no-op, so there is no double-count
|
|
118
|
+
// path, and the WHERE guard means a row can only ever move UP.
|
|
119
|
+
raiseOnConflict = false,
|
|
108
120
|
}) {
|
|
109
121
|
// V3.R11 (#91): builder_id is the per-builder attribution column added by
|
|
110
122
|
// migration 046. Routes default it to the authed builder, so the only
|
|
111
123
|
// legitimately-null builder_id is for historical rows or system-injected
|
|
112
124
|
// costs (infra, domain, etc.) that don't belong to any one person.
|
|
125
|
+
// Monotonic raise (opt-in) vs the historical insert-once. `recorded_at` moves
|
|
126
|
+
// with the amount so the reconciler's "digest is newer than the priced row"
|
|
127
|
+
// predicate settles instead of re-firing every sweep.
|
|
128
|
+
const conflictAction = raiseOnConflict
|
|
129
|
+
? `DO UPDATE SET
|
|
130
|
+
amount_usd = EXCLUDED.amount_usd,
|
|
131
|
+
description = EXCLUDED.description,
|
|
132
|
+
fresh_input_usd = EXCLUDED.fresh_input_usd,
|
|
133
|
+
cache_read_usd = EXCLUDED.cache_read_usd,
|
|
134
|
+
cache_write_usd = EXCLUDED.cache_write_usd,
|
|
135
|
+
output_usd = EXCLUDED.output_usd,
|
|
136
|
+
recorded_at = EXCLUDED.recorded_at
|
|
137
|
+
WHERE EXCLUDED.amount_usd > cost_log.amount_usd`
|
|
138
|
+
: 'DO NOTHING';
|
|
113
139
|
const { rows } = await pool.query(
|
|
114
140
|
`INSERT INTO cost_log (task_id, amount_usd, category, description, source, source_ref, recorded_at, builder_id,
|
|
115
141
|
fresh_input_usd, cache_read_usd, cache_write_usd, output_usd, skill_name)
|
|
116
142
|
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, now()), $8, $9, $10, $11, $12, $13)
|
|
117
143
|
ON CONFLICT (source, source_ref)
|
|
118
144
|
WHERE source IS NOT NULL AND source_ref IS NOT NULL
|
|
119
|
-
|
|
145
|
+
${conflictAction}
|
|
120
146
|
RETURNING id, recorded_at`,
|
|
121
147
|
[taskId, amountUsd, category, description, source, sourceRef, recordedAt, builderId,
|
|
122
148
|
freshInputUsd, cacheReadUsd, cacheWriteUsd, outputUsd, skillName || null]
|
|
123
149
|
);
|
|
124
|
-
|
|
150
|
+
// null when the conflict clause skipped the write (DO NOTHING, or a raise that
|
|
151
|
+
// would not have moved the row upward).
|
|
152
|
+
return rows[0] ?? null;
|
|
125
153
|
}
|
|
126
154
|
|
|
127
155
|
// task 1366 (System 1) — server-side session-cost reconciler.
|
|
@@ -144,25 +172,45 @@ async function logCost({
|
|
|
144
172
|
// first crack at posting (avoids racing it). 15m default.
|
|
145
173
|
// - limit : per-sweep cap (runaway guard; there are normally few).
|
|
146
174
|
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
//
|
|
175
|
+
// A session the CLIENT split into interactive + subagent rows (session_id ||
|
|
176
|
+
// ':sub', task 1344) is skipped entirely — we hold only the combined
|
|
177
|
+
// model_usage, so we cannot reproduce that split and should defer to it.
|
|
178
|
+
//
|
|
179
|
+
// task 1003217 — WHY THIS NO LONGER SKIPS EVERY PRICED SESSION. It used to
|
|
180
|
+
// exclude any session that had a cost row at all. But `session_records` is
|
|
181
|
+
// upserted on EVERY ship, so a session that ships twelve tasks has a digest
|
|
182
|
+
// from its FIRST ship, and this sweep priced that partial digest ~15 minutes
|
|
183
|
+
// later and then never looked again — logCost's DO NOTHING silently dropped
|
|
184
|
+
// every subsequent, larger figure. Measured on prod: a 9.3-hour session was
|
|
185
|
+
// billed at its first 56 minutes, and across four audited sessions the ledger
|
|
186
|
+
// captured 14%, 14%, 16% and 54% of real spend. Now a session is revisited
|
|
187
|
+
// while its digest is NEWER than the row we priced from it, and logCost raises
|
|
188
|
+
// the row monotonically. `recorded_at` advances on each raise, so a settled
|
|
189
|
+
// session stops matching and the sweep converges.
|
|
190
|
+
//
|
|
191
|
+
// Historical rows are NOT re-priced downward: llm-pricing.js is explicit that a
|
|
192
|
+
// paid row records what was charged, and ADR 0054 paid credits from it. The
|
|
193
|
+
// raise is upward-only, so pre-fix inflated rows stay as they are — expect a
|
|
194
|
+
// visible step change in cost-per-ship at deploy rather than a rewritten past.
|
|
195
|
+
// Returns { scanned, reconciled, raised, totalUsd, unknownModels } for logging.
|
|
153
196
|
async function reconcileSessionCosts({ olderThanMinutes = 15, limit = 500 } = {}) {
|
|
154
197
|
const mins = Number.isFinite(Number(olderThanMinutes)) ? Number(olderThanMinutes) : 15;
|
|
155
198
|
const lim = Number.isFinite(Number(limit)) ? Number(limit) : 500;
|
|
156
199
|
const { rows } = await pool.query(
|
|
157
|
-
`SELECT sr.session_id, sr.builder_id, sr.model_usage
|
|
200
|
+
`SELECT sr.session_id, sr.builder_id, sr.model_usage,
|
|
201
|
+
c.amount_usd AS prior_usd
|
|
158
202
|
FROM session_records sr
|
|
203
|
+
LEFT JOIN cost_log c
|
|
204
|
+
ON c.source = 'session:interactive'
|
|
205
|
+
AND c.source_ref = sr.session_id
|
|
159
206
|
WHERE sr.model_usage IS NOT NULL
|
|
160
207
|
AND sr.uploaded_at < now() - ($1 || ' minutes')::interval
|
|
161
208
|
AND NOT EXISTS (
|
|
162
|
-
SELECT 1 FROM cost_log
|
|
163
|
-
WHERE
|
|
164
|
-
OR c.source_ref = sr.session_id || ':sub'
|
|
209
|
+
SELECT 1 FROM cost_log s
|
|
210
|
+
WHERE s.source_ref = sr.session_id || ':sub'
|
|
165
211
|
)
|
|
212
|
+
-- Never priced, or the digest has grown since we priced it.
|
|
213
|
+
AND (c.id IS NULL OR c.recorded_at < sr.uploaded_at)
|
|
166
214
|
ORDER BY sr.uploaded_at DESC
|
|
167
215
|
LIMIT $2`,
|
|
168
216
|
[String(mins), lim]
|
|
@@ -170,6 +218,7 @@ async function reconcileSessionCosts({ olderThanMinutes = 15, limit = 500 } = {}
|
|
|
170
218
|
|
|
171
219
|
const round4 = (n) => Math.round((Number(n) || 0) * 10000) / 10000;
|
|
172
220
|
let reconciled = 0;
|
|
221
|
+
let raised = 0;
|
|
173
222
|
let totalUsd = 0;
|
|
174
223
|
const unknownModels = new Set();
|
|
175
224
|
for (const r of rows) {
|
|
@@ -177,34 +226,50 @@ async function reconcileSessionCosts({ olderThanMinutes = 15, limit = 500 } = {}
|
|
|
177
226
|
for (const m of comp.unknown_models) unknownModels.add(m);
|
|
178
227
|
const amount = round4(comp.total_usd);
|
|
179
228
|
if (!(amount > 0)) continue; // nothing priceable on this row — skip
|
|
229
|
+
const prior = round4(r.prior_usd);
|
|
230
|
+
// A row already at or above this figure needs no write: the digest grew but
|
|
231
|
+
// the price did not (or the stored row predates a pricing fix and is higher,
|
|
232
|
+
// which we deliberately leave alone).
|
|
233
|
+
if (prior > 0 && amount <= prior) continue;
|
|
180
234
|
const id8 = String(r.session_id).slice(0, 8);
|
|
181
235
|
const unkNote = comp.unknown_models.length
|
|
182
236
|
? ` [unpriced model(s) priced as opus: ${comp.unknown_models.join(',')}]`
|
|
183
237
|
: '';
|
|
238
|
+
const provenance = prior > 0
|
|
239
|
+
? `raised from $${prior.toFixed(4)} as the session grew`
|
|
240
|
+
: 'reconciled from digest; client cost-hook did not post';
|
|
184
241
|
const inserted = await logCost({
|
|
185
242
|
amountUsd: amount,
|
|
186
243
|
category: 'api',
|
|
187
244
|
source: 'session:interactive',
|
|
188
|
-
// SAME key the client would use
|
|
189
|
-
//
|
|
245
|
+
// SAME key the client would use, so a client post and this sweep can
|
|
246
|
+
// never both land as separate rows.
|
|
190
247
|
sourceRef: r.session_id,
|
|
191
248
|
builderId: r.builder_id,
|
|
192
|
-
|
|
249
|
+
// Upward-only: catches a long session up as it ships more tasks, and can
|
|
250
|
+
// never lower a row that has already been paid from.
|
|
251
|
+
raiseOnConflict: true,
|
|
252
|
+
description: `session ${id8} — $${amount.toFixed(4)} (${provenance})${unkNote}`.slice(0, 1000),
|
|
193
253
|
freshInputUsd: round4(comp.fresh_input_usd),
|
|
194
254
|
cacheReadUsd: round4(comp.cache_read_usd),
|
|
195
255
|
cacheWriteUsd: round4(comp.cache_write_usd),
|
|
196
256
|
outputUsd: round4(comp.output_usd),
|
|
197
257
|
});
|
|
198
|
-
// inserted === null means
|
|
199
|
-
// SELECT and the INSERT
|
|
258
|
+
// inserted === null means the conflict clause skipped the write (the client
|
|
259
|
+
// raced in between the SELECT and the INSERT, or the raise would not have
|
|
260
|
+
// moved the row up) — expected + idempotent, not counted.
|
|
200
261
|
if (inserted) {
|
|
201
|
-
|
|
202
|
-
|
|
262
|
+
if (prior > 0) raised++;
|
|
263
|
+
else reconciled++;
|
|
264
|
+
// Bill only the INCREMENT on a raise, so this figure stays a true
|
|
265
|
+
// "spend recorded by this sweep" rather than re-counting the whole row.
|
|
266
|
+
totalUsd += amount - prior;
|
|
203
267
|
}
|
|
204
268
|
}
|
|
205
269
|
return {
|
|
206
270
|
scanned: rows.length,
|
|
207
271
|
reconciled,
|
|
272
|
+
raised,
|
|
208
273
|
totalUsd: round4(totalUsd),
|
|
209
274
|
unknownModels: Array.from(unknownModels),
|
|
210
275
|
};
|