settld 0.1.1 → 0.1.5

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.
Files changed (441) hide show
  1. package/README.md +61 -3
  2. package/SETTLD_VERSION +1 -1
  3. package/bin/settld-mcp +2 -0
  4. package/bin/settld.js +13 -0
  5. package/conformance/kernel-v0/README.md +7 -0
  6. package/conformance/kernel-v0/run.mjs +292 -4
  7. package/docs/ACCESS.md +57 -0
  8. package/docs/ADOPTION_CHECKLIST.md +44 -0
  9. package/docs/ALERTS.md +198 -0
  10. package/docs/ARCHITECTURE.md +69 -0
  11. package/docs/ARCHITECTURE_FOUNDER_GUIDE.md +284 -0
  12. package/docs/ARTIFACTS.md +60 -0
  13. package/docs/CERTIFICATION_CHECKLIST.md +33 -0
  14. package/docs/CIRCLE_SANDBOX_E2E.md +140 -0
  15. package/docs/CONFIG.md +297 -0
  16. package/docs/CONTRACTS_APIS.md +23 -0
  17. package/docs/DEPRECATION.md +31 -0
  18. package/docs/DOMAIN_MODEL.md +92 -0
  19. package/docs/EVENT_ENVELOPE.md +53 -0
  20. package/docs/FINANCE_PACK_FORMAT.md +53 -0
  21. package/docs/INCIDENT_TAXONOMY.md +30 -0
  22. package/docs/JOB_STATE_MACHINE.md +66 -0
  23. package/docs/KERNEL_COMPATIBLE.md +60 -0
  24. package/docs/KERNEL_V0.md +40 -0
  25. package/docs/KEY_ROTATION.md +80 -0
  26. package/docs/LEDGER.md +82 -0
  27. package/docs/LIVENESS.md +76 -0
  28. package/docs/MVP_BUILD_ORDER.md +36 -0
  29. package/docs/ONCALL_PLAYBOOK.md +39 -0
  30. package/docs/OPERATIONS_SIGNING.md +20 -0
  31. package/docs/OVERVIEW.md +190 -0
  32. package/docs/PERF_BASELINE.md +85 -0
  33. package/docs/PRD.md +77 -0
  34. package/docs/QUICKSTART_KERNEL_V0.md +96 -0
  35. package/docs/QUICKSTART_MCP.md +337 -0
  36. package/docs/QUICKSTART_MCP_HOSTS.md +143 -0
  37. package/docs/QUICKSTART_PRODUCE.md +61 -0
  38. package/docs/QUICKSTART_RELEASE_VERIFY.md +39 -0
  39. package/docs/QUICKSTART_SDK.md +125 -0
  40. package/docs/QUICKSTART_SDK_PYTHON.md +111 -0
  41. package/docs/QUICKSTART_VERIFY.md +54 -0
  42. package/docs/QUICKSTART_X402_GATEWAY.md +317 -0
  43. package/docs/README.md +15 -0
  44. package/docs/RELEASE_CHECKLIST.md +156 -0
  45. package/docs/RELEASING.md +81 -0
  46. package/docs/REPO_SETTINGS.md +37 -0
  47. package/docs/RUNBOOK.md +86 -0
  48. package/docs/SKILLS.md +42 -0
  49. package/docs/SKILL_BUNDLE_FORMAT.md +48 -0
  50. package/docs/SLO.md +70 -0
  51. package/docs/SUMMARY.md +16 -0
  52. package/docs/SUPPORT.md +31 -0
  53. package/docs/THREAT_MODEL.md +36 -0
  54. package/docs/TRUST.md +59 -0
  55. package/docs/WORKFLOW.md +35 -0
  56. package/docs/X402_BATCH_SETTLEMENT.md +126 -0
  57. package/docs/blog/2026-02-14-your-ai-agent-just-spent-500-where-is-the-receipt.md +73 -0
  58. package/docs/examples/x402-provider-payout-registry.example.json +14 -0
  59. package/docs/gitbook/README.md +52 -0
  60. package/docs/gitbook/SETUP.md +25 -0
  61. package/docs/gitbook/SUMMARY.md +15 -0
  62. package/docs/gitbook/api-reference.md +73 -0
  63. package/docs/gitbook/closepacks.md +55 -0
  64. package/docs/gitbook/conformance.md +59 -0
  65. package/docs/gitbook/core-primitives.md +85 -0
  66. package/docs/gitbook/dispute-lifecycle.md +33 -0
  67. package/docs/gitbook/faq.md +21 -0
  68. package/docs/gitbook/guides.md +49 -0
  69. package/docs/gitbook/operations-runbook.md +36 -0
  70. package/docs/gitbook/quickstart.md +104 -0
  71. package/docs/gitbook/replay-and-audit.md +30 -0
  72. package/docs/gitbook/sdk-reference.md +35 -0
  73. package/docs/gitbook/security-model.md +58 -0
  74. package/docs/integrations/README.md +14 -0
  75. package/docs/integrations/github-actions-verify.yml +31 -0
  76. package/docs/integrations/github-actions.md +34 -0
  77. package/docs/integrations/openclaw/CLAWHUB_PUBLISH_CHECKLIST.md +65 -0
  78. package/docs/integrations/openclaw/settld-mcp-skill/SKILL.md +69 -0
  79. package/docs/integrations/openclaw/settld-mcp-skill/mcp-server.example.json +12 -0
  80. package/docs/kernel-compatible/capabilities.json +36 -0
  81. package/docs/marketing/agent-commerce-substrate.md +78 -0
  82. package/docs/marketing/hn-repost-2026-02-17.md +102 -0
  83. package/docs/marketing/show-hn-post.md +45 -0
  84. package/docs/ops/ARTIFACT_VERIFICATION_STATUS.md +43 -0
  85. package/docs/ops/BILLING_WEBHOOK_REPLAY.md +105 -0
  86. package/docs/ops/CI_FLAKE_BUDGET.md +31 -0
  87. package/docs/ops/GO_LIVE_GATE_S13.md +27 -0
  88. package/docs/ops/HOSTED_BASELINE_R2.md +129 -0
  89. package/docs/ops/KERNEL_V0_SHIP_GATE.md +67 -0
  90. package/docs/ops/LIGHTHOUSE_PRODUCTION_CLOSE.md +51 -0
  91. package/docs/ops/MCP_COMPATIBILITY_MATRIX.md +28 -0
  92. package/docs/ops/MINIMUM_PRODUCTION_TOPOLOGY.md +89 -0
  93. package/docs/ops/P0_BACKEND_PROGRESS.md +150 -0
  94. package/docs/ops/PAYMENTS_ALPHA_R5.md +105 -0
  95. package/docs/ops/PILOT_ONBOARDING_RUNBOOK.md +112 -0
  96. package/docs/ops/PRODUCTION_DEPLOYMENT_CHECKLIST.md +103 -0
  97. package/docs/ops/R1_SLOS.md +66 -0
  98. package/docs/ops/RELEASE_SIGNING_INCIDENT.md +58 -0
  99. package/docs/ops/SELF_SERVE_LAUNCH_AUTOMATION.md +89 -0
  100. package/docs/ops/THROUGHPUT_DRILL_10X.md +48 -0
  101. package/docs/ops/TRUST_CONFIG_WIZARD.md +47 -0
  102. package/docs/ops/X402_PILOT_WEEKLY_METRICS.md +76 -0
  103. package/docs/ops/tool-call-disputes-holdback.md +52 -0
  104. package/docs/pilot-kit/PILOT_PACKAGE_SCORECARD_X402.md +46 -0
  105. package/docs/pilot-kit/README.md +29 -0
  106. package/docs/pilot-kit/architecture-one-pager.md +48 -0
  107. package/docs/pilot-kit/buyer-email.txt +19 -0
  108. package/docs/pilot-kit/buyer-one-pager.md +31 -0
  109. package/docs/pilot-kit/gtm-pilot-playbook.md +182 -0
  110. package/docs/pilot-kit/offline-verify.md +33 -0
  111. package/docs/pilot-kit/procurement-one-pager.md +50 -0
  112. package/docs/pilot-kit/rfp-clause.md +46 -0
  113. package/docs/pilot-kit/roi-calculator-template.csv +2 -0
  114. package/docs/pilot-kit/security-qa.md +153 -0
  115. package/docs/pilot-kit/security-summary.md +35 -0
  116. package/docs/plans/2026-02-13-mcp-spike-design.md +113 -0
  117. package/docs/spec/AcceptanceCriteria.v1.md +17 -0
  118. package/docs/spec/AcceptanceEvaluation.v1.md +10 -0
  119. package/docs/spec/AgentEvent.v1.md +47 -0
  120. package/docs/spec/AgentIdentity.v1.md +62 -0
  121. package/docs/spec/AgentPassport.v1.md +95 -0
  122. package/docs/spec/AgentReputation.v1.md +59 -0
  123. package/docs/spec/AgentReputation.v2.md +52 -0
  124. package/docs/spec/AgentRun.v1.md +47 -0
  125. package/docs/spec/AgentRunSettlement.v1.md +52 -0
  126. package/docs/spec/AgentWallet.v1.md +43 -0
  127. package/docs/spec/AgreementDelegation.v1.md +109 -0
  128. package/docs/spec/ArbitrationCase.v1.md +67 -0
  129. package/docs/spec/ArbitrationVerdict.v1.md +60 -0
  130. package/docs/spec/BundleHeadAttestation.v1.md +32 -0
  131. package/docs/spec/CANONICAL_JSON.md +31 -0
  132. package/docs/spec/CRYPTOGRAPHY.md +61 -0
  133. package/docs/spec/ClosePack.v1.md +49 -0
  134. package/docs/spec/ClosePackManifest.v1.md +24 -0
  135. package/docs/spec/DelegationGrant.v1.md +90 -0
  136. package/docs/spec/DisputeOpenEnvelope.v1.md +43 -0
  137. package/docs/spec/ERRORS.md +76 -0
  138. package/docs/spec/ESCROW_NETTING_INVARIANTS.md +71 -0
  139. package/docs/spec/EvidenceIndex.v1.md +20 -0
  140. package/docs/spec/ExecutionIntent.v1.md +90 -0
  141. package/docs/spec/FinancePackBundleManifest.v1.md +24 -0
  142. package/docs/spec/FundingHold.v1.md +60 -0
  143. package/docs/spec/GovernancePolicy.v1.md +34 -0
  144. package/docs/spec/GovernancePolicy.v2.md +30 -0
  145. package/docs/spec/INVARIANTS.md +389 -0
  146. package/docs/spec/InteractionDirectionMatrix.v1.md +30 -0
  147. package/docs/spec/InvoiceBundleManifest.v1.md +24 -0
  148. package/docs/spec/InvoiceClaim.v1.md +11 -0
  149. package/docs/spec/MONEY_RAIL_STATE_MACHINE.md +58 -0
  150. package/docs/spec/MarketplaceAcceptance.v2.md +46 -0
  151. package/docs/spec/MarketplaceOffer.v2.md +54 -0
  152. package/docs/spec/MeteringReport.v1.md +18 -0
  153. package/docs/spec/PRODUCER_ERRORS.md +42 -0
  154. package/docs/spec/PricingMatrix.v1.md +20 -0
  155. package/docs/spec/PricingMatrixSignatures.v1.md +30 -0
  156. package/docs/spec/PricingMatrixSignatures.v2.md +29 -0
  157. package/docs/spec/ProduceCliOutput.v1.md +46 -0
  158. package/docs/spec/ProofBundleManifest.v1.md +24 -0
  159. package/docs/spec/README.md +104 -0
  160. package/docs/spec/REFERENCE_IMPLEMENTATIONS.md +29 -0
  161. package/docs/spec/REFERENCE_VERIFIER_BEHAVIOR.md +68 -0
  162. package/docs/spec/REMOTE_SIGNER.md +66 -0
  163. package/docs/spec/ReleaseIndex.v1.md +32 -0
  164. package/docs/spec/ReleaseIndexSignatures.v1.md +17 -0
  165. package/docs/spec/ReleaseTrust.v1.md +13 -0
  166. package/docs/spec/ReleaseTrust.v2.md +26 -0
  167. package/docs/spec/RemoteSignerRequest.v1.md +21 -0
  168. package/docs/spec/RemoteSignerResponse.v1.md +16 -0
  169. package/docs/spec/ReputationEvent.v1.md +63 -0
  170. package/docs/spec/RevocationList.v1.md +28 -0
  171. package/docs/spec/SIGNER_PROVIDER_PLUGIN.md +32 -0
  172. package/docs/spec/STRICTNESS.md +68 -0
  173. package/docs/spec/SUPPLY_CHAIN.md +33 -0
  174. package/docs/spec/SettlementAdjustment.v1.md +45 -0
  175. package/docs/spec/SettlementDecisionRecord.v1.md +48 -0
  176. package/docs/spec/SettlementDecisionRecord.v2.md +51 -0
  177. package/docs/spec/SettlementDecisionReport.v1.md +44 -0
  178. package/docs/spec/SettlementKernel.v1.md +59 -0
  179. package/docs/spec/SettlementReceipt.v1.md +63 -0
  180. package/docs/spec/SlaDefinition.v1.md +24 -0
  181. package/docs/spec/SlaEvaluation.v1.md +12 -0
  182. package/docs/spec/THREAT_MODEL.md +113 -0
  183. package/docs/spec/TOOL_PROVENANCE.md +30 -0
  184. package/docs/spec/TRUST_ANCHORS.md +84 -0
  185. package/docs/spec/TenantSettings.v1.md +90 -0
  186. package/docs/spec/TenantSettings.v2.md +99 -0
  187. package/docs/spec/TimestampProof.v1.md +25 -0
  188. package/docs/spec/ToolCallAgreement.v1.md +34 -0
  189. package/docs/spec/ToolCallEvidence.v1.md +47 -0
  190. package/docs/spec/ToolManifest.v1.md +47 -0
  191. package/docs/spec/VERIFIER_ENVIRONMENT.md +38 -0
  192. package/docs/spec/VERSIONING.md +107 -0
  193. package/docs/spec/VerificationReport.v1.md +50 -0
  194. package/docs/spec/VerifyAboutOutput.v1.md +10 -0
  195. package/docs/spec/VerifyCliOutput.v1.md +28 -0
  196. package/docs/spec/WARNINGS.md +83 -0
  197. package/docs/spec/error-codes.v1.txt +285 -0
  198. package/docs/spec/examples/agreement_delegation_v1.example.json +21 -0
  199. package/docs/spec/examples/arbitration_case_v1.example.json +26 -0
  200. package/docs/spec/examples/arbitration_verdict_v1.example.json +32 -0
  201. package/docs/spec/examples/dispute_open_envelope_v1.example.json +18 -0
  202. package/docs/spec/examples/produce_cli_output_v1.example.json +32 -0
  203. package/docs/spec/examples/release_index_signature_v1.example.json +9 -0
  204. package/docs/spec/examples/release_index_signatures_v1.example.json +14 -0
  205. package/docs/spec/examples/release_index_v1.example.json +15 -0
  206. package/docs/spec/examples/release_trust_v1.example.json +7 -0
  207. package/docs/spec/examples/release_trust_v2.example.json +22 -0
  208. package/docs/spec/examples/remote_signer_request_v1.example.json +18 -0
  209. package/docs/spec/examples/remote_signer_response_v1.example.json +8 -0
  210. package/docs/spec/examples/reputation_event_v1.example.json +29 -0
  211. package/docs/spec/examples/verification_report_v1.example.json +24 -0
  212. package/docs/spec/examples/verify_about_output_v1.example.json +29 -0
  213. package/docs/spec/examples/verify_cli_output_v1.example.json +13 -0
  214. package/docs/spec/legacy/MarketplaceAcceptance.v1.md +48 -0
  215. package/docs/spec/legacy/MarketplaceOffer.v1.md +56 -0
  216. package/docs/spec/legacy/schemas/MarketplaceAcceptance.v1.schema.json +53 -0
  217. package/docs/spec/legacy/schemas/MarketplaceOffer.v1.schema.json +61 -0
  218. package/docs/spec/producer-error-codes.v1.txt +14 -0
  219. package/docs/spec/schemas/AcceptanceCriteria.v1.schema.json +24 -0
  220. package/docs/spec/schemas/AcceptanceEvaluation.v1.schema.json +26 -0
  221. package/docs/spec/schemas/AgentEvent.v1.schema.json +49 -0
  222. package/docs/spec/schemas/AgentIdentity.v1.schema.json +129 -0
  223. package/docs/spec/schemas/AgentPassport.v1.schema.json +112 -0
  224. package/docs/spec/schemas/AgentReputation.v1.schema.json +151 -0
  225. package/docs/spec/schemas/AgentReputation.v2.schema.json +120 -0
  226. package/docs/spec/schemas/AgentRun.v1.schema.json +71 -0
  227. package/docs/spec/schemas/AgentRunSettlement.v1.schema.json +75 -0
  228. package/docs/spec/schemas/AgentWallet.v1.schema.json +54 -0
  229. package/docs/spec/schemas/AgreementDelegation.v1.schema.json +50 -0
  230. package/docs/spec/schemas/ArbitrationCase.v1.schema.json +133 -0
  231. package/docs/spec/schemas/ArbitrationVerdict.v1.schema.json +149 -0
  232. package/docs/spec/schemas/BundleHeadAttestation.v1.schema.json +21 -0
  233. package/docs/spec/schemas/ClosePackManifest.v1.schema.json +38 -0
  234. package/docs/spec/schemas/DelegationGrant.v1.schema.json +102 -0
  235. package/docs/spec/schemas/DisputeOpenEnvelope.v1.schema.json +78 -0
  236. package/docs/spec/schemas/EvidenceIndex.v1.schema.json +41 -0
  237. package/docs/spec/schemas/ExecutionIntent.v1.schema.json +85 -0
  238. package/docs/spec/schemas/FinancePackBundleManifest.v1.schema.json +38 -0
  239. package/docs/spec/schemas/FundingHold.v1.schema.json +46 -0
  240. package/docs/spec/schemas/GovernancePolicy.v1.schema.json +45 -0
  241. package/docs/spec/schemas/GovernancePolicy.v2.schema.json +70 -0
  242. package/docs/spec/schemas/InteractionDirectionMatrix.v1.schema.json +43 -0
  243. package/docs/spec/schemas/InvoiceBundleManifest.v1.schema.json +38 -0
  244. package/docs/spec/schemas/InvoiceClaim.v1.schema.json +39 -0
  245. package/docs/spec/schemas/MarketplaceAcceptance.v2.schema.json +53 -0
  246. package/docs/spec/schemas/MarketplaceOffer.v2.schema.json +61 -0
  247. package/docs/spec/schemas/MeteringReport.v1.schema.json +45 -0
  248. package/docs/spec/schemas/PricingMatrix.v1.schema.json +24 -0
  249. package/docs/spec/schemas/PricingMatrixSignatures.v1.schema.json +24 -0
  250. package/docs/spec/schemas/PricingMatrixSignatures.v2.schema.json +24 -0
  251. package/docs/spec/schemas/ProduceCliOutput.v1.schema.json +107 -0
  252. package/docs/spec/schemas/ProofBundleManifest.v1.schema.json +37 -0
  253. package/docs/spec/schemas/PublicKeys.v1.schema.json +33 -0
  254. package/docs/spec/schemas/ReleaseIndex.v1.schema.json +45 -0
  255. package/docs/spec/schemas/ReleaseIndexSignature.v1.schema.json +16 -0
  256. package/docs/spec/schemas/ReleaseIndexSignatures.v1.schema.json +16 -0
  257. package/docs/spec/schemas/ReleaseTrust.v1.schema.json +15 -0
  258. package/docs/spec/schemas/ReleaseTrust.v2.schema.json +37 -0
  259. package/docs/spec/schemas/RemoteSignerPublicKeyResponse.v1.schema.json +14 -0
  260. package/docs/spec/schemas/RemoteSignerRequest.v1.schema.json +24 -0
  261. package/docs/spec/schemas/RemoteSignerResponse.v1.schema.json +10 -0
  262. package/docs/spec/schemas/RemoteSignerSignRequest.v1.schema.json +27 -0
  263. package/docs/spec/schemas/RemoteSignerSignResponse.v1.schema.json +16 -0
  264. package/docs/spec/schemas/ReputationEvent.v1.schema.json +164 -0
  265. package/docs/spec/schemas/RevocationList.v1.schema.json +51 -0
  266. package/docs/spec/schemas/SettlementAdjustment.v1.schema.json +44 -0
  267. package/docs/spec/schemas/SettlementDecisionRecord.v1.schema.json +66 -0
  268. package/docs/spec/schemas/SettlementDecisionRecord.v2.schema.json +148 -0
  269. package/docs/spec/schemas/SettlementDecisionReport.v1.schema.json +61 -0
  270. package/docs/spec/schemas/SettlementReceipt.v1.schema.json +135 -0
  271. package/docs/spec/schemas/SlaDefinition.v1.schema.json +33 -0
  272. package/docs/spec/schemas/SlaEvaluation.v1.schema.json +26 -0
  273. package/docs/spec/schemas/TenantSettings.v1.schema.json +90 -0
  274. package/docs/spec/schemas/TenantSettings.v2.schema.json +161 -0
  275. package/docs/spec/schemas/TimestampProof.v1.schema.json +17 -0
  276. package/docs/spec/schemas/ToolCallAgreement.v1.schema.json +34 -0
  277. package/docs/spec/schemas/ToolCallEvidence.v1.schema.json +45 -0
  278. package/docs/spec/schemas/ToolManifest.v1.schema.json +54 -0
  279. package/docs/spec/schemas/VerificationReport.v1.schema.json +83 -0
  280. package/docs/spec/schemas/VerifyAboutOutput.v1.schema.json +54 -0
  281. package/docs/spec/schemas/VerifyCliOutput.v1.schema.json +75 -0
  282. package/docs/spec/schemas/VerifyReleaseOutput.v1.schema.json +47 -0
  283. package/docs/spec/x402-error-codes.v1.txt +21 -0
  284. package/docs/templates/buyer-email.txt +18 -0
  285. package/docs/templates/buyer-one-pager.md +24 -0
  286. package/package.json +40 -6
  287. package/scripts/acceptance/full-stack.mjs +734 -0
  288. package/scripts/acceptance/full-stack.sh +99 -0
  289. package/scripts/audit/build-audit-packet.mjs +242 -0
  290. package/scripts/backup-pg.sh +45 -0
  291. package/scripts/backup-restore/README.md +18 -0
  292. package/scripts/backup-restore/capture-state.mjs +130 -0
  293. package/scripts/backup-restore/client.mjs +97 -0
  294. package/scripts/backup-restore/seed-workload.mjs +235 -0
  295. package/scripts/backup-restore/verify-state.mjs +139 -0
  296. package/scripts/backup-restore-test.sh +217 -0
  297. package/scripts/chaos.js +221 -0
  298. package/scripts/ci/build-launch-cutover-packet.mjs +148 -0
  299. package/scripts/ci/build-self-serve-benchmark-report.mjs +122 -0
  300. package/scripts/ci/changelog-guard.mjs +145 -0
  301. package/scripts/ci/check-kernel-v0-launch-gate.mjs +233 -0
  302. package/scripts/ci/check-secret-hygiene.mjs +78 -0
  303. package/scripts/ci/check-version-consistency.mjs +42 -0
  304. package/scripts/ci/cli-pack-smoke.mjs +160 -0
  305. package/scripts/ci/flake-budget-guard.mjs +68 -0
  306. package/scripts/ci/generate-error-codes.mjs +54 -0
  307. package/scripts/ci/lib/lighthouse-tracker.mjs +90 -0
  308. package/scripts/ci/lib/self-serve-launch-gate.mjs +89 -0
  309. package/scripts/ci/npm-pack-smoke.mjs +454 -0
  310. package/scripts/ci/run-10x-throughput-drill.mjs +246 -0
  311. package/scripts/ci/run-10x-throughput-incident-rehearsal.mjs +325 -0
  312. package/scripts/ci/run-arbitration-workspace-browser-e2e.sh +22 -0
  313. package/scripts/ci/run-circle-sandbox-smoke.mjs +237 -0
  314. package/scripts/ci/run-go-live-gate.mjs +150 -0
  315. package/scripts/ci/run-kernel-v0-ship-gate.mjs +97 -0
  316. package/scripts/ci/run-mcp-host-smoke.mjs +275 -0
  317. package/scripts/ci/run-self-serve-launch-gate.mjs +56 -0
  318. package/scripts/ci/runtime-import-smoke.mjs +58 -0
  319. package/scripts/ci/update-lighthouse-tracker.mjs +112 -0
  320. package/scripts/closepack/lib.mjs +286 -0
  321. package/scripts/collect-debug.sh +263 -0
  322. package/scripts/demo/compositional-settlement-3hop.mjs +237 -0
  323. package/scripts/demo/delivery-robot/export-ui-fixture.mjs +188 -0
  324. package/scripts/demo/delivery-robot/generate.mjs +377 -0
  325. package/scripts/demo/kernel-agent-goes-shopping.mjs +202 -0
  326. package/scripts/demo/magic-link-first-green.mjs +118 -0
  327. package/scripts/demo/magic-link-kind-smoke.mjs +577 -0
  328. package/scripts/demo/mcp-paid-exa.mjs +1110 -0
  329. package/scripts/dev/billing-doctor.sh +145 -0
  330. package/scripts/dev/billing-smoke-prod.sh +219 -0
  331. package/scripts/dev/billing-webhook-replay.sh +161 -0
  332. package/scripts/dev/env.dev.example +29 -0
  333. package/scripts/dev/env.sh +37 -0
  334. package/scripts/dev/new-sdk-key.sh +81 -0
  335. package/scripts/dev/sdk-first-run.sh +21 -0
  336. package/scripts/dev/smoke-x402-gateway.sh +115 -0
  337. package/scripts/dev/start-api.sh +24 -0
  338. package/scripts/examples/produce-and-verify-jobproof.mjs +191 -0
  339. package/scripts/examples/sdk-first-paid-rfq.py +105 -0
  340. package/scripts/examples/sdk-first-verified-run.mjs +85 -0
  341. package/scripts/examples/sdk-first-verified-run.py +99 -0
  342. package/scripts/examples/sdk-tenant-analytics.mjs +103 -0
  343. package/scripts/examples/sdk-tenant-analytics.py +118 -0
  344. package/scripts/finance-pack/bundle.mjs +284 -0
  345. package/scripts/fixtures/generate-bundle-fixtures.mjs +877 -0
  346. package/scripts/governance/export.mjs +169 -0
  347. package/scripts/load/delivery-stress.k6.js +183 -0
  348. package/scripts/load/ingest-burst.k6.js +236 -0
  349. package/scripts/load/run-delivery-load.js +66 -0
  350. package/scripts/load/webhook-receiver.js +131 -0
  351. package/scripts/magic-link/migrate-run-records-to-db.mjs +35 -0
  352. package/scripts/mcp/probe.mjs +238 -0
  353. package/scripts/mcp/settld-mcp-http-gateway.mjs +178 -0
  354. package/scripts/mcp/settld-mcp-server.mjs +1201 -0
  355. package/scripts/openapi/write.mjs +13 -0
  356. package/scripts/ops/bootstrap-tenant-conformance.mjs +185 -0
  357. package/scripts/ops/build-x402-pilot-reliability-report.mjs +489 -0
  358. package/scripts/ops/check-x402-receipt-sample.mjs +181 -0
  359. package/scripts/ops/design-partner-run-packet.mjs +466 -0
  360. package/scripts/ops/hosted-baseline-evidence.mjs +681 -0
  361. package/scripts/ops/money-rails-chargeback-evidence.mjs +509 -0
  362. package/scripts/ops/money-rails-reconcile-evidence.mjs +180 -0
  363. package/scripts/ops/p0-seed-money-rail-operation.mjs +432 -0
  364. package/scripts/pilot/finance-pack.mjs +495 -0
  365. package/scripts/pilot/fixtures/robot-keypair.json +4 -0
  366. package/scripts/pilot/fixtures/server-signer.json +4 -0
  367. package/scripts/proof-bundle/job.mjs +109 -0
  368. package/scripts/proof-bundle/lib.mjs +92 -0
  369. package/scripts/proof-bundle/month.mjs +103 -0
  370. package/scripts/provider/conformance-run.mjs +159 -0
  371. package/scripts/provider/keys-generate.mjs +135 -0
  372. package/scripts/provider/publish.mjs +420 -0
  373. package/scripts/quickstart/x402.mjs +334 -0
  374. package/scripts/release/build-artifacts.mjs +181 -0
  375. package/scripts/release/generate-release-index.mjs +112 -0
  376. package/scripts/release/release-index-lib.mjs +232 -0
  377. package/scripts/release/sign-release-index.mjs +85 -0
  378. package/scripts/release/validate-release-assets.mjs +170 -0
  379. package/scripts/release/verify-release.mjs +261 -0
  380. package/scripts/restore-pg.sh +34 -0
  381. package/scripts/scaffold/create-settld-paid-tool.mjs +19 -0
  382. package/scripts/sdk/smoke-python.py +30 -0
  383. package/scripts/sdk/smoke.mjs +16 -0
  384. package/scripts/settlement/x402-batch-worker.mjs +1091 -0
  385. package/scripts/slo/check.mjs +178 -0
  386. package/scripts/smoke/k8s-smoke.mjs +214 -0
  387. package/scripts/spec/generate-protocol-vectors.mjs +931 -0
  388. package/scripts/test/check-no-generated-artifacts.sh +12 -0
  389. package/scripts/test/run.sh +45 -0
  390. package/scripts/trust/validate-trust-file.mjs +57 -0
  391. package/scripts/trust-config/rotate-settld-pay.mjs +277 -0
  392. package/scripts/trust-config/wizard.mjs +161 -0
  393. package/scripts/vendor-contract-test-lib.mjs +182 -0
  394. package/scripts/vendor-contract-test.mjs +55 -0
  395. package/scripts/vercel/build-mkdocs.sh +9 -0
  396. package/scripts/vercel/ignore-mkdocs.sh +25 -0
  397. package/scripts/vercel/install-mkdocs.sh +6 -0
  398. package/scripts/verify-pg.js +217 -0
  399. package/scripts/x402/receipt-verify.mjs +289 -0
  400. package/services/finance-sink/src/dedupe-store.js +29 -6
  401. package/services/receiver/src/dedupe-store.js +29 -5
  402. package/services/x402-gateway/Dockerfile +13 -0
  403. package/services/x402-gateway/README.md +58 -0
  404. package/services/x402-gateway/examples/upstream-mock.js +337 -0
  405. package/services/x402-gateway/src/server.js +947 -0
  406. package/src/api/app.js +32517 -16877
  407. package/src/api/maintenance.js +70 -0
  408. package/src/api/openapi.js +1130 -17
  409. package/src/api/persistence.js +272 -0
  410. package/src/api/server.js +81 -5
  411. package/src/api/store.js +1248 -6
  412. package/src/api/workers/deliveries.js +99 -4
  413. package/src/api/workers/insolvency-sweep.js +159 -0
  414. package/src/core/agent-card.js +69 -0
  415. package/src/core/agent-wallets.js +97 -0
  416. package/src/core/agreement-delegation.js +549 -0
  417. package/src/core/billing-plans.js +40 -6
  418. package/src/core/circle-reserve-adapter.js +845 -0
  419. package/src/core/maintenance-locks.js +1 -0
  420. package/src/core/paid-tool-manifest.js +318 -0
  421. package/src/core/provider-publish-conformance.js +525 -0
  422. package/src/core/provider-publish-proof.js +396 -0
  423. package/src/core/provider-quote-signature.js +170 -0
  424. package/src/core/settld-keys.js +112 -0
  425. package/src/core/settld-pay-token.js +344 -0
  426. package/src/core/settlement-kernel.js +213 -2
  427. package/src/core/settlement-verifier.js +335 -0
  428. package/src/core/tool-call-agreement.js +112 -0
  429. package/src/core/tool-call-evidence.js +144 -0
  430. package/src/core/tool-provider-signature.js +98 -0
  431. package/src/core/x402-escalation-override.js +258 -0
  432. package/src/core/x402-gate.js +118 -0
  433. package/src/core/x402-provider-refund-decision.js +220 -0
  434. package/src/core/x402-receipt-verifier.js +708 -0
  435. package/src/core/x402-reversal-command.js +251 -0
  436. package/src/core/x402-wallet-issuer-decision.js +252 -0
  437. package/src/core/zk-verifier.js +300 -0
  438. package/src/db/migrations/029_reputation_event_index.sql +54 -0
  439. package/src/db/migrations/030_artifacts_source_event_unique_job_only.sql +15 -0
  440. package/src/db/pg.js +18 -7
  441. package/src/db/store-pg.js +838 -72
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env node
2
+ import { Readable } from "node:stream";
3
+
4
+ import { createApi } from "../src/api/app.js";
5
+ import { createStore } from "../src/api/store.js";
6
+ import { createPgStore } from "../src/db/store-pg.js";
7
+
8
+ function parseArgs(argv) {
9
+ const out = {};
10
+ for (let i = 0; i < argv.length; i += 1) {
11
+ const a = argv[i];
12
+ if (!a.startsWith("--")) continue;
13
+ const key = a.slice(2);
14
+ const next = argv[i + 1];
15
+ if (next && !next.startsWith("--")) {
16
+ out[key] = next;
17
+ i += 1;
18
+ } else {
19
+ out[key] = "true";
20
+ }
21
+ }
22
+ return out;
23
+ }
24
+
25
+ function makeReq({ method, path, headers, body }) {
26
+ const chunks = body === undefined ? [] : [Buffer.from(JSON.stringify(body), "utf8")];
27
+ const req = Readable.from(chunks);
28
+ req.method = method;
29
+ req.url = path;
30
+ req.headers = headers ?? {};
31
+ return req;
32
+ }
33
+
34
+ function makeRes() {
35
+ const headers = new Map();
36
+ return {
37
+ statusCode: 200,
38
+ setHeader(name, value) {
39
+ headers.set(String(name).toLowerCase(), String(value));
40
+ },
41
+ end(payload) {
42
+ this.body = payload ?? "";
43
+ this.headers = headers;
44
+ this.ended = true;
45
+ }
46
+ };
47
+ }
48
+
49
+ async function request(api, { method, path, body, headers }) {
50
+ const reqHeaders = { ...(headers ?? {}) };
51
+ if (body !== undefined) reqHeaders["content-type"] = "application/json";
52
+ const req = makeReq({ method, path, headers: reqHeaders, body });
53
+ const res = makeRes();
54
+ await api.handle(req, res);
55
+ const text = typeof res.body === "string" ? res.body : Buffer.from(res.body ?? "").toString("utf8");
56
+ const json = text ? JSON.parse(text) : null;
57
+ return { statusCode: res.statusCode, json, headers: res.headers };
58
+ }
59
+
60
+ function sleep(ms) {
61
+ return new Promise((r) => setTimeout(r, ms));
62
+ }
63
+
64
+ async function main() {
65
+ const args = parseArgs(process.argv.slice(2));
66
+
67
+ const mode = args.store ?? process.env.STORE ?? (process.env.DATABASE_URL ? "pg" : "memory");
68
+ const jobsCount = Number(args.jobs ?? "200");
69
+ const robotsCount = Number(args.robots ?? "20");
70
+ const dispatchWorkers = Number(args["dispatch-workers"] ?? "2");
71
+ const zoneId = args.zone ?? "zone_default";
72
+
73
+ if (!Number.isSafeInteger(jobsCount) || jobsCount <= 0) throw new Error("--jobs must be a positive integer");
74
+ if (!Number.isSafeInteger(robotsCount) || robotsCount <= 0) throw new Error("--robots must be a positive integer");
75
+ if (!Number.isSafeInteger(dispatchWorkers) || dispatchWorkers <= 0) throw new Error("--dispatch-workers must be a positive integer");
76
+
77
+ let schema = args.schema ?? null;
78
+ const databaseUrl = process.env.DATABASE_URL ?? null;
79
+ if (mode === "pg") {
80
+ if (!databaseUrl) throw new Error("STORE=pg requires DATABASE_URL");
81
+ if (!schema) schema = `chaos_${Date.now()}_${Math.random().toString(16).slice(2)}`;
82
+ }
83
+
84
+ const stores = [];
85
+ const apis = [];
86
+
87
+ if (mode === "pg") {
88
+ for (let i = 0; i < dispatchWorkers; i += 1) {
89
+ const store = await createPgStore({ databaseUrl, schema, dropSchemaOnClose: i === 0 });
90
+ stores.push(store);
91
+ apis.push(createApi({ store }));
92
+ }
93
+ } else {
94
+ const store = createStore();
95
+ stores.push(store);
96
+ apis.push(createApi({ store }));
97
+ }
98
+
99
+ const api0 = apis[0];
100
+ const now = Date.now();
101
+ const availStartAt = new Date(now - 60 * 60_000).toISOString();
102
+ const availEndAt = new Date(now + 48 * 60 * 60_000).toISOString();
103
+
104
+ // Seed robots.
105
+ for (let i = 0; i < robotsCount; i += 1) {
106
+ const robotId = `rob_chaos_${i}`;
107
+ const reg = await request(api0, { method: "POST", path: "/robots/register", body: { robotId, trustScore: 0.8, homeZoneId: zoneId } });
108
+ if (reg.statusCode !== 201) throw new Error(`robot register failed: ${JSON.stringify(reg.json)}`);
109
+ const prev = reg.json.robot.lastChainHash;
110
+ const avail = await request(api0, {
111
+ method: "POST",
112
+ path: `/robots/${robotId}/availability`,
113
+ headers: { "x-proxy-expected-prev-chain-hash": prev },
114
+ body: { availability: [{ startAt: availStartAt, endAt: availEndAt }], timezone: "UTC" }
115
+ });
116
+ if (avail.statusCode !== 201) throw new Error(`robot availability failed: ${JSON.stringify(avail.json)}`);
117
+ }
118
+
119
+ // Create jobs (booked + dispatch requested).
120
+ const pilotStartBase = new Date(now + 10 * 60_000).toISOString();
121
+ for (let i = 0; i < jobsCount; i += 1) {
122
+ const startAt = new Date(Date.parse(pilotStartBase) + (i % 120) * 60_000).toISOString(); // spread over ~2h
123
+ const res = await request(api0, {
124
+ method: "POST",
125
+ path: "/pilot/jobs",
126
+ body: { startAt, autoBook: true, zoneId }
127
+ });
128
+ if (res.statusCode !== 201 && res.statusCode !== 409) {
129
+ throw new Error(`pilot job create failed: status=${res.statusCode} body=${JSON.stringify(res.json)}`);
130
+ }
131
+ }
132
+
133
+ if (mode !== "pg") {
134
+ // Single-process dispatch loop for memory store.
135
+ let loops = 0;
136
+ while (loops < 10_000) {
137
+ loops += 1;
138
+ const r = await api0.tickDispatch({ maxMessages: 100 });
139
+ if (!r.processed.length) break;
140
+ }
141
+ console.log(`dispatch processed (memory): jobs=${jobsCount}`);
142
+ return;
143
+ }
144
+
145
+ const pool = stores[0].pg.pool;
146
+ async function countPending(topic) {
147
+ const res = await pool.query("SELECT COUNT(*)::int AS c FROM outbox WHERE processed_at IS NULL AND topic = $1", [topic]);
148
+ return Number(res.rows[0].c);
149
+ }
150
+
151
+ // Dispatch loop with random restarts.
152
+ let tick = 0;
153
+ while (true) {
154
+ const pending = await countPending("DISPATCH_REQUESTED");
155
+ if (pending === 0) break;
156
+
157
+ tick += 1;
158
+ await Promise.all(apis.map((api) => api.tickDispatch({ maxMessages: 100 })));
159
+
160
+ // Randomly restart one worker every ~10 ticks.
161
+ if (tick % 10 === 0 && apis.length > 1) {
162
+ const idx = 1 + Math.floor(Math.random() * (apis.length - 1));
163
+ const store = stores[idx];
164
+ await store.close();
165
+ const newStore = await createPgStore({ databaseUrl, schema, dropSchemaOnClose: false });
166
+ stores[idx] = newStore;
167
+ apis[idx] = createApi({ store: newStore });
168
+ }
169
+
170
+ // Avoid tight loop.
171
+ await sleep(25);
172
+ }
173
+
174
+ // Invariants.
175
+ const confirmedRes = await pool.query(
176
+ `
177
+ SELECT aggregate_id, COUNT(*) FILTER (WHERE type = 'DISPATCH_CONFIRMED')::int AS confirmed
178
+ FROM events
179
+ WHERE aggregate_type = 'job'
180
+ GROUP BY aggregate_id
181
+ `
182
+ );
183
+ for (const row of confirmedRes.rows) {
184
+ const confirmed = Number(row.confirmed);
185
+ if (confirmed > 1) throw new Error(`invariant violation: job ${row.aggregate_id} has ${confirmed} DISPATCH_CONFIRMED events`);
186
+ }
187
+
188
+ const pendingDispatch = await countPending("DISPATCH_REQUESTED");
189
+ const pendingLedgerRes = await pool.query("SELECT COUNT(*)::int AS c FROM outbox WHERE processed_at IS NULL AND topic = 'LEDGER_ENTRY_APPLY'");
190
+ const pendingNotifyRes = await pool.query("SELECT COUNT(*)::int AS c FROM outbox WHERE processed_at IS NULL AND topic LIKE 'NOTIFY_%'");
191
+
192
+ console.log(
193
+ JSON.stringify(
194
+ {
195
+ schema,
196
+ jobsCount,
197
+ robotsCount,
198
+ dispatchWorkers,
199
+ pending: {
200
+ dispatch: pendingDispatch,
201
+ ledger: Number(pendingLedgerRes.rows[0].c),
202
+ notify: Number(pendingNotifyRes.rows[0].c)
203
+ },
204
+ jobsConfirmedChecked: confirmedRes.rows.length
205
+ },
206
+ null,
207
+ 2
208
+ )
209
+ );
210
+
211
+ for (const store of stores) {
212
+ await store.close();
213
+ }
214
+ }
215
+
216
+ main().catch((err) => {
217
+ // eslint-disable-next-line no-console
218
+ console.error(err);
219
+ process.exit(1);
220
+ });
221
+
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname, resolve } from "node:path";
4
+ import { loadLighthouseTrackerFromPath } from "./lib/lighthouse-tracker.mjs";
5
+
6
+ async function readJson(pathname) {
7
+ try {
8
+ const raw = await readFile(pathname, "utf8");
9
+ return { ok: true, value: JSON.parse(raw) };
10
+ } catch (err) {
11
+ return { ok: false, error: err?.message ?? "unable to read JSON file" };
12
+ }
13
+ }
14
+
15
+ function checkFromGoLiveGate(gateReport) {
16
+ const checks = Array.isArray(gateReport?.checks) ? gateReport.checks : [];
17
+ const byId = new Map(checks.map((row) => [String(row?.id ?? ""), row]));
18
+ const deterministic = byId.get("deterministic_critical_suite") ?? null;
19
+ const throughput = byId.get("throughput_10x_drill") ?? null;
20
+ const incidentRehearsal = byId.get("throughput_incident_rehearsal") ?? null;
21
+ const lighthouse = byId.get("lighthouse_customers_paid_production") ?? null;
22
+ return {
23
+ deterministic,
24
+ throughput,
25
+ incidentRehearsal,
26
+ lighthouse
27
+ };
28
+ }
29
+
30
+ async function main() {
31
+ const packetPath = resolve(process.cwd(), process.env.LAUNCH_CUTOVER_PACKET_PATH || "artifacts/gates/s13-launch-cutover-packet.json");
32
+ const gateReportPath = resolve(process.cwd(), process.env.GO_LIVE_GATE_REPORT_PATH || "artifacts/gates/s13-go-live-gate.json");
33
+ const throughputReportPath = resolve(process.cwd(), process.env.THROUGHPUT_REPORT_PATH || "artifacts/throughput/10x-drill-summary.json");
34
+ const incidentRehearsalReportPath = resolve(
35
+ process.cwd(),
36
+ process.env.THROUGHPUT_INCIDENT_REHEARSAL_REPORT_PATH || "artifacts/throughput/10x-incident-rehearsal-summary.json"
37
+ );
38
+ const lighthouseTrackerPath = resolve(
39
+ process.cwd(),
40
+ process.env.LIGHTHOUSE_TRACKER_PATH || "planning/launch/lighthouse-production-tracker.json"
41
+ );
42
+ await mkdir(dirname(packetPath), { recursive: true });
43
+
44
+ const gateRead = await readJson(gateReportPath);
45
+ const throughputRead = await readJson(throughputReportPath);
46
+ const incidentRehearsalRead = await readJson(incidentRehearsalReportPath);
47
+ let lighthouse = null;
48
+ let lighthouseLoadError = null;
49
+ try {
50
+ lighthouse = await loadLighthouseTrackerFromPath(lighthouseTrackerPath);
51
+ } catch (err) {
52
+ lighthouseLoadError = err?.message ?? "unable to load lighthouse tracker";
53
+ }
54
+
55
+ const gateCheckRefs = gateRead.ok ? checkFromGoLiveGate(gateRead.value) : null;
56
+ const checks = [
57
+ {
58
+ id: "go_live_gate_report_present",
59
+ ok: gateRead.ok,
60
+ path: gateReportPath,
61
+ details: gateRead.ok ? null : gateRead.error
62
+ },
63
+ {
64
+ id: "go_live_gate_verdict_ok",
65
+ ok: gateRead.ok ? gateRead.value?.verdict?.ok === true : false,
66
+ path: gateReportPath,
67
+ details: gateRead.ok
68
+ ? {
69
+ requiredChecks: gateRead.value?.verdict?.requiredChecks ?? null,
70
+ passedChecks: gateRead.value?.verdict?.passedChecks ?? null
71
+ }
72
+ : null
73
+ },
74
+ {
75
+ id: "throughput_report_present",
76
+ ok: throughputRead.ok,
77
+ path: throughputReportPath,
78
+ details: throughputRead.ok ? null : throughputRead.error
79
+ },
80
+ {
81
+ id: "throughput_verdict_ok",
82
+ ok: throughputRead.ok ? throughputRead.value?.verdict?.ok === true : false,
83
+ path: throughputReportPath,
84
+ details: throughputRead.ok ? { runner: throughputRead.value?.runConfig?.runner ?? null } : null
85
+ },
86
+ {
87
+ id: "throughput_incident_rehearsal_report_present",
88
+ ok: incidentRehearsalRead.ok,
89
+ path: incidentRehearsalReportPath,
90
+ details: incidentRehearsalRead.ok ? null : incidentRehearsalRead.error
91
+ },
92
+ {
93
+ id: "throughput_incident_rehearsal_verdict_ok",
94
+ ok: incidentRehearsalRead.ok ? incidentRehearsalRead.value?.verdict?.ok === true : false,
95
+ path: incidentRehearsalReportPath,
96
+ details: incidentRehearsalRead.ok
97
+ ? {
98
+ requiredChecks: incidentRehearsalRead.value?.verdict?.requiredChecks ?? null,
99
+ passedChecks: incidentRehearsalRead.value?.verdict?.passedChecks ?? null
100
+ }
101
+ : null
102
+ },
103
+ {
104
+ id: "lighthouse_tracker_ready",
105
+ ok: lighthouse?.ok === true,
106
+ path: lighthouseTrackerPath,
107
+ details: lighthouse ?? { error: lighthouseLoadError }
108
+ }
109
+ ];
110
+
111
+ const blockingIssues = [];
112
+ for (const check of checks) {
113
+ if (check.ok === true) continue;
114
+ blockingIssues.push({
115
+ checkId: check.id,
116
+ path: check.path ?? null,
117
+ details: check.details ?? null
118
+ });
119
+ }
120
+
121
+ const report = {
122
+ schemaVersion: "LaunchCutoverPacket.v1",
123
+ generatedAt: new Date().toISOString(),
124
+ sources: {
125
+ goLiveGateReportPath: gateReportPath,
126
+ throughputReportPath,
127
+ incidentRehearsalReportPath,
128
+ lighthouseTrackerPath
129
+ },
130
+ checks,
131
+ gateReference: gateCheckRefs,
132
+ blockingIssues,
133
+ verdict: {
134
+ ok: checks.every((row) => row.ok === true),
135
+ requiredChecks: checks.length,
136
+ passedChecks: checks.filter((row) => row.ok === true).length
137
+ }
138
+ };
139
+
140
+ await writeFile(packetPath, JSON.stringify(report, null, 2) + "\n", "utf8");
141
+ process.stdout.write(`wrote launch cutover packet: ${packetPath}\n`);
142
+ if (report.verdict.ok !== true) process.exitCode = 1;
143
+ }
144
+
145
+ main().catch((err) => {
146
+ process.stderr.write(`${err?.stack || err?.message || String(err)}\n`);
147
+ process.exit(1);
148
+ });
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname, resolve } from "node:path";
4
+
5
+ async function readJsonBestEffort(pathname) {
6
+ try {
7
+ return JSON.parse(await readFile(pathname, "utf8"));
8
+ } catch (err) {
9
+ return { _error: err?.message ?? "unable to read json" };
10
+ }
11
+ }
12
+
13
+ function pickGateMetric(summary, key) {
14
+ const rows = Array.isArray(summary?.metrics) ? summary.metrics : [];
15
+ const found = rows.find((row) => row?.key === key);
16
+ return found && Number.isFinite(Number(found.value)) ? Number(found.value) : null;
17
+ }
18
+
19
+ function pickTrackerMetric(tracker, key) {
20
+ const row = tracker?.metrics?.[key];
21
+ return row && Number.isFinite(Number(row.value)) ? Number(row.value) : null;
22
+ }
23
+
24
+ async function main() {
25
+ const launchGatePath = resolve(
26
+ process.cwd(),
27
+ process.env.SELF_SERVE_LAUNCH_GATE_REPORT_PATH || "artifacts/gates/self-serve-launch-gate.json"
28
+ );
29
+ const throughputPath = resolve(
30
+ process.cwd(),
31
+ process.env.THROUGHPUT_REPORT_PATH || "artifacts/throughput/10x-drill-summary.json"
32
+ );
33
+ const incidentPath = resolve(
34
+ process.cwd(),
35
+ process.env.THROUGHPUT_INCIDENT_REHEARSAL_REPORT_PATH || "artifacts/throughput/10x-incident-rehearsal-summary.json"
36
+ );
37
+ const outPath = resolve(
38
+ process.cwd(),
39
+ process.env.SELF_SERVE_BENCHMARK_REPORT_PATH || "artifacts/launch/self-serve-benchmark-report.json"
40
+ );
41
+ await mkdir(dirname(outPath), { recursive: true });
42
+
43
+ const launchGate = await readJsonBestEffort(launchGatePath);
44
+ const throughput = await readJsonBestEffort(throughputPath);
45
+ const incident = await readJsonBestEffort(incidentPath);
46
+
47
+ const launchSummary = launchGate?.checks?.[0]?.summary ?? null;
48
+ const launchGateOk = launchGate?.verdict?.ok === true;
49
+ const throughputOk = throughput?.verdict?.ok === true;
50
+ const incidentOk = incident?.verdict?.ok === true;
51
+ const trackerPath =
52
+ typeof launchGate?.checks?.[0]?.trackerPath === "string" && launchGate.checks[0].trackerPath.trim() !== ""
53
+ ? launchGate.checks[0].trackerPath
54
+ : null;
55
+ const tracker = trackerPath ? await readJsonBestEffort(trackerPath) : null;
56
+
57
+ const referralLinkShares = pickGateMetric(launchSummary, "referralLinkShares") ?? pickTrackerMetric(tracker, "referralLinkShares");
58
+ const referralSignups = pickGateMetric(launchSummary, "referralSignups") ?? pickTrackerMetric(tracker, "referralSignups");
59
+ const referralConversionRatePct =
60
+ pickGateMetric(launchSummary, "referralConversionRatePct") ?? pickTrackerMetric(tracker, "referralConversionRatePct");
61
+
62
+ const report = {
63
+ schemaVersion: "SelfServeBenchmarkReport.v1",
64
+ generatedAt: new Date().toISOString(),
65
+ sources: {
66
+ launchGatePath,
67
+ throughputPath,
68
+ incidentPath
69
+ },
70
+ benchmark: {
71
+ launchKpis: {
72
+ gateOk: launchGateOk,
73
+ mvsvUsd: pickGateMetric(launchSummary, "mvsvUsd"),
74
+ signups: pickGateMetric(launchSummary, "signups"),
75
+ teamsFirstLiveSettlement: pickGateMetric(launchSummary, "teamsFirstLiveSettlement"),
76
+ payingCustomers: pickGateMetric(launchSummary, "payingCustomers"),
77
+ medianTimeToFirstSettlementMinutes: pickGateMetric(launchSummary, "medianTimeToFirstSettlementMinutes"),
78
+ arbitrationMedianResolutionHours: pickGateMetric(launchSummary, "arbitrationMedianResolutionHours")
79
+ },
80
+ throughput10x: {
81
+ ok: throughputOk,
82
+ httpReqDurationP95Ms: Number.isFinite(Number(throughput?.metrics?.httpReqDurationP95Ms))
83
+ ? Number(throughput.metrics.httpReqDurationP95Ms)
84
+ : null,
85
+ httpReqFailedRate: Number.isFinite(Number(throughput?.metrics?.httpReqFailedRate))
86
+ ? Number(throughput.metrics.httpReqFailedRate)
87
+ : null,
88
+ ingestRejectedPerMin: Number.isFinite(Number(throughput?.metrics?.ingestRejectedPerMin))
89
+ ? Number(throughput.metrics.ingestRejectedPerMin)
90
+ : null
91
+ },
92
+ incidentRehearsal: {
93
+ ok: incidentOk,
94
+ durationMs: Number.isFinite(Number(incident?.durationMs)) ? Number(incident.durationMs) : null,
95
+ failedChecks: Array.isArray(incident?.checks) ? incident.checks.filter((row) => row?.ok !== true).map((row) => row?.id).filter(Boolean) : []
96
+ },
97
+ referral: {
98
+ linkShares: referralLinkShares,
99
+ signups: referralSignups,
100
+ conversionRatePct: referralConversionRatePct
101
+ }
102
+ }
103
+ };
104
+
105
+ report.verdict = {
106
+ ok: Boolean(launchGateOk && throughputOk && incidentOk),
107
+ checks: {
108
+ launchGateOk,
109
+ throughputOk,
110
+ incidentOk
111
+ }
112
+ };
113
+
114
+ await writeFile(outPath, JSON.stringify(report, null, 2) + "\n", "utf8");
115
+ process.stdout.write(`wrote self-serve benchmark report: ${outPath}\n`);
116
+ if (!report.verdict.ok) process.exitCode = 1;
117
+ }
118
+
119
+ main().catch((err) => {
120
+ process.stderr.write(`${err?.stack || err?.message || String(err)}\n`);
121
+ process.exit(1);
122
+ });
@@ -0,0 +1,145 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import fs from "node:fs";
3
+
4
+ function loadV1FreezeFiles() {
5
+ try {
6
+ const raw = fs.readFileSync("test/fixtures/protocol-v1-freeze.json", "utf8");
7
+ const json = JSON.parse(raw);
8
+ const files = json?.files && typeof json.files === "object" && !Array.isArray(json.files) ? Object.keys(json.files) : [];
9
+ return new Set(files);
10
+ } catch {
11
+ return new Set();
12
+ }
13
+ }
14
+
15
+ const V1_FROZEN_FILES = loadV1FreezeFiles();
16
+
17
+ function usage() {
18
+ // eslint-disable-next-line no-console
19
+ console.error("usage: node scripts/ci/changelog-guard.mjs --base <sha> --head <sha>");
20
+ process.exit(2);
21
+ }
22
+
23
+ function parseArgs(argv) {
24
+ let base = null;
25
+ let head = null;
26
+ for (let i = 0; i < argv.length; i += 1) {
27
+ const a = argv[i];
28
+ if (a === "--base") {
29
+ base = argv[i + 1] ?? null;
30
+ i += 1;
31
+ continue;
32
+ }
33
+ if (a === "--head") {
34
+ head = argv[i + 1] ?? null;
35
+ i += 1;
36
+ continue;
37
+ }
38
+ if (a === "--help" || a === "-h") usage();
39
+ usage();
40
+ }
41
+ if (!base || !head) usage();
42
+ return { base, head };
43
+ }
44
+
45
+ function changedFiles(base, head) {
46
+ const out = execFileSync("git", ["diff", "--name-only", `${base}..${head}`], { encoding: "utf8" });
47
+ return out
48
+ .split("\n")
49
+ .map((s) => s.trim())
50
+ .filter(Boolean);
51
+ }
52
+
53
+ function commitMessages(base, head) {
54
+ try {
55
+ const out = execFileSync("git", ["log", "--format=%B", `${base}..${head}`], { encoding: "utf8" });
56
+ return String(out ?? "");
57
+ } catch {
58
+ return "";
59
+ }
60
+ }
61
+
62
+ function readLabelsFromGithubEvent() {
63
+ try {
64
+ const p = process.env.GITHUB_EVENT_PATH ?? null;
65
+ if (!p || !fs.existsSync(p)) return [];
66
+ const raw = fs.readFileSync(p, "utf8");
67
+ const json = JSON.parse(raw);
68
+ const labels = json?.pull_request?.labels ?? [];
69
+ if (!Array.isArray(labels)) return [];
70
+ return labels.map((l) => String(l?.name ?? "")).filter(Boolean);
71
+ } catch {
72
+ return [];
73
+ }
74
+ }
75
+
76
+ function readPrBodyFromGithubEvent() {
77
+ try {
78
+ const p = process.env.GITHUB_EVENT_PATH ?? null;
79
+ if (!p || !fs.existsSync(p)) return "";
80
+ const raw = fs.readFileSync(p, "utf8");
81
+ const json = JSON.parse(raw);
82
+ return String(json?.pull_request?.body ?? "");
83
+ } catch {
84
+ return "";
85
+ }
86
+ }
87
+
88
+ function matchesProtocolSurface(fp) {
89
+ const prefixes = [
90
+ "docs/spec/",
91
+ "scripts/spec/",
92
+ "test/fixtures/protocol-vectors/",
93
+ "test/fixtures/bundles/"
94
+ ];
95
+ return prefixes.some((p) => fp.startsWith(p));
96
+ }
97
+
98
+ function isV1FrozenSurface(fp) {
99
+ return V1_FROZEN_FILES.has(fp);
100
+ }
101
+
102
+ function hasProtocolChangeMarker(text) {
103
+ const t = String(text ?? "").toLowerCase();
104
+ return t.includes("[protocol-change]") || t.includes("protocol-change:");
105
+ }
106
+
107
+ const { base, head } = parseArgs(process.argv.slice(2));
108
+ const files = changedFiles(base, head);
109
+ const touchedChangelog = files.includes("CHANGELOG.md");
110
+ const protocolSurfaceChanged = files.some(matchesProtocolSurface);
111
+ const v1FrozenChanged = files.some(isV1FrozenSurface);
112
+ const labels = readLabelsFromGithubEvent();
113
+ const hasReleaseNoteLabel = labels.includes("release-note");
114
+
115
+ if (!touchedChangelog && (protocolSurfaceChanged || hasReleaseNoteLabel)) {
116
+ // eslint-disable-next-line no-console
117
+ console.error("CHANGELOG.md must be updated for this PR.");
118
+ // eslint-disable-next-line no-console
119
+ if (protocolSurfaceChanged) console.error("- Reason: protocol surface files changed (docs/spec, schemas, vectors, or fixtures).");
120
+ // eslint-disable-next-line no-console
121
+ if (hasReleaseNoteLabel) console.error("- Reason: PR is labeled release-note.");
122
+ process.exit(1);
123
+ }
124
+
125
+ if (v1FrozenChanged && process.env.ALLOW_PROTOCOL_V1_MUTATION !== "1") {
126
+ const markerText = `${readPrBodyFromGithubEvent()}\n${commitMessages(base, head)}`;
127
+ const hasMarker = hasProtocolChangeMarker(markerText);
128
+ if (!hasMarker || !touchedChangelog) {
129
+ // eslint-disable-next-line no-console
130
+ console.error("Protocol v1 freeze gate: v1 schemas/vectors changed.");
131
+ // eslint-disable-next-line no-console
132
+ console.error("- This requires (1) CHANGELOG.md update and (2) an explicit protocol-change marker in the PR body or commit message.");
133
+ // eslint-disable-next-line no-console
134
+ console.error("- Marker examples: [protocol-change] or protocol-change:");
135
+ // eslint-disable-next-line no-console
136
+ console.error("- Override (local only): ALLOW_PROTOCOL_V1_MUTATION=1");
137
+ // eslint-disable-next-line no-console
138
+ console.error("Changed frozen files:");
139
+ for (const fp of files.filter(isV1FrozenSurface)) {
140
+ // eslint-disable-next-line no-console
141
+ console.error(`- ${fp}`);
142
+ }
143
+ process.exit(1);
144
+ }
145
+ }