@1aboveio/skills 0.19.2 → 0.20.1

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 (203) hide show
  1. package/README.md +9 -4
  2. package/package.json +1 -1
  3. package/runtime/skills/distribution/generated/recipes.json +54 -48
  4. package/runtime/skills/distribution/scripts/bundles.mjs +113 -7
  5. package/runtime/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
  6. package/runtime/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
  7. package/skills/cicd-pipeline/mergify/SKILL.md +1 -1
  8. package/skills/engineering/engineering-runtime/coherence/workflow.json +14 -83
  9. package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
  10. package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
  11. package/skills/engineering/smoke/SKILL.md +1 -1
  12. package/skills/payment/payment-analysis/SKILL.md +13 -7
  13. package/skills/payment/payment-analysis/references/chargebacks.md +43 -18
  14. package/skills/payment/payment-analysis/references/event-layers.md +4 -0
  15. package/skills/payment/payment-analysis/references/metrics.md +9 -7
  16. package/skills/payment/payment-analysis/references/report-template.md +3 -3
  17. package/skills/payment/payment-analysis/references/terminology.md +6 -1
  18. package/skills/payment/payment-analysis/references/visualization.md +1 -1
  19. package/skills/payment/tld-detection/SKILL.md +163 -0
  20. package/skills/payment/tld-detection/agents/openai.yaml +9 -0
  21. package/skills/payment/tld-detection/evals/evals.json +107 -0
  22. package/skills/payment/tld-detection/references/clean.md +51 -0
  23. package/skills/payment/tld-detection/references/clustering.md +219 -0
  24. package/skills/payment/tld-detection/references/decision.md +85 -0
  25. package/skills/payment/tld-detection/references/report-template.md +169 -0
  26. package/skills/payment/tld-detection/references/terminology.md +69 -0
  27. package/skills/payment/tld-detection/references/workflow.md +78 -0
  28. package/skills/payment/tld-detection/scripts/detect_ladders.py +390 -0
  29. package/skills/payment/tld-detection/tests/test_detect_ladders.py +132 -0
  30. package/skills/engineering/resolve-issues/SKILL.md +0 -168
  31. package/skills/engineering/resolve-issues/agents/openai.yaml +0 -9
  32. package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +0 -499
  33. package/skills/engineering/resolve-issues/references/breaker.md +0 -82
  34. package/skills/engineering/resolve-issues/references/deliverables.md +0 -27
  35. package/skills/engineering/resolve-issues/references/delivery.md +0 -108
  36. package/skills/engineering/resolve-issues/references/evidence-lane.md +0 -21
  37. package/skills/engineering/resolve-issues/references/exact-head-ci.md +0 -287
  38. package/skills/engineering/resolve-issues/references/fan-out.md +0 -33
  39. package/skills/engineering/resolve-issues/references/finalization.md +0 -68
  40. package/skills/engineering/resolve-issues/references/guarantees.md +0 -10
  41. package/skills/engineering/resolve-issues/references/high-risk.md +0 -29
  42. package/skills/engineering/resolve-issues/references/incidents/848/README.md +0 -156
  43. package/skills/engineering/resolve-issues/references/intake.md +0 -86
  44. package/skills/engineering/resolve-issues/references/integration-gate.md +0 -53
  45. package/skills/engineering/resolve-issues/references/interference.md +0 -87
  46. package/skills/engineering/resolve-issues/references/loop.md +0 -134
  47. package/skills/engineering/resolve-issues/references/model-catalog.md +0 -9
  48. package/skills/engineering/resolve-issues/references/postmortem.md +0 -27
  49. package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +0 -41
  50. package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +0 -48
  51. package/skills/engineering/resolve-issues/references/pre-flight.md +0 -41
  52. package/skills/engineering/resolve-issues/references/regression-checklist.md +0 -26
  53. package/skills/engineering/resolve-issues/references/run-state.md +0 -288
  54. package/skills/engineering/resolve-issues/references/sandboxed-testing.md +0 -48
  55. package/skills/engineering/resolve-issues/references/spawn-contract.md +0 -96
  56. package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +0 -40
  57. package/skills/engineering/resolve-issues/references/why.md +0 -653
  58. package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +0 -49
  59. package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +0 -721
  60. package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +0 -962
  61. package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +0 -220
  62. package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +0 -420
  63. package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +0 -256
  64. package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +0 -168
  65. package/skills/engineering/resolve-issues/scripts/discover-models.mjs +0 -9
  66. package/skills/engineering/resolve-issues/scripts/doctrine.mjs +0 -62
  67. package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +0 -191
  68. package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +0 -413
  69. package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +0 -332
  70. package/skills/engineering/resolve-issues/scripts/finalize.mjs +0 -488
  71. package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +0 -3307
  72. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +0 -16
  73. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +0 -51
  74. package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +0 -17
  75. package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +0 -166
  76. package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +0 -92
  77. package/skills/engineering/resolve-issues/scripts/guide-index.mjs +0 -73
  78. package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +0 -159
  79. package/skills/engineering/resolve-issues/scripts/interference.mjs +0 -427
  80. package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +0 -9
  81. package/skills/engineering/resolve-issues/scripts/next-operations.mjs +0 -419
  82. package/skills/engineering/resolve-issues/scripts/postmortem.mjs +0 -909
  83. package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +0 -345
  84. package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +0 -415
  85. package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +0 -697
  86. package/skills/engineering/resolve-issues/scripts/report.mjs +0 -494
  87. package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +0 -172
  88. package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +0 -79
  89. package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +0 -334
  90. package/skills/engineering/resolve-issues/scripts/run-state.mjs +0 -4792
  91. package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +0 -395
  92. package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +0 -290
  93. package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +0 -170
  94. package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +0 -293
  95. package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +0 -197
  96. package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +0 -127
  97. package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +0 -893
  98. package/skills/engineering/resolve-issues/scripts/workspaces.mjs +0 -829
  99. package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +0 -290
  100. package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +0 -80
  101. package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +0 -102
  102. package/skills/engineering/resolve-release/LICENSE +0 -3
  103. package/skills/engineering/resolve-release/SKILL.md +0 -113
  104. package/skills/engineering/resolve-release/agents/openai.yaml +0 -9
  105. package/skills/engineering/resolve-release/references/assembly.md +0 -137
  106. package/skills/engineering/resolve-release/references/auto-when-green.md +0 -56
  107. package/skills/engineering/resolve-release/references/candidate.md +0 -167
  108. package/skills/engineering/resolve-release/references/exposure.md +0 -178
  109. package/skills/engineering/resolve-release/references/handoff.md +0 -24
  110. package/skills/engineering/resolve-release/references/postmortem.md +0 -230
  111. package/skills/engineering/resolve-release/references/preflight.md +0 -208
  112. package/skills/engineering/resolve-release/references/principles.md +0 -94
  113. package/skills/engineering/resolve-release/references/regression-checklist.md +0 -36
  114. package/skills/engineering/resolve-release/references/related-skills.md +0 -13
  115. package/skills/engineering/resolve-release/references/routing.md +0 -149
  116. package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +0 -285
  117. package/skills/engineering/resolve-release/references/versioning.md +0 -202
  118. package/skills/engineering/resolve-release/references/why.md +0 -53
  119. package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +0 -389
  120. package/skills/engineering/resolve-release/scripts/build-changes.mjs +0 -209
  121. package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +0 -407
  122. package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +0 -904
  123. package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +0 -81
  124. package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +0 -612
  125. package/skills/engineering/resolve-release/scripts/close-attempt.mjs +0 -135
  126. package/skills/engineering/resolve-release/scripts/closeout-release.mjs +0 -161
  127. package/skills/engineering/resolve-release/scripts/doctrine.mjs +0 -106
  128. package/skills/engineering/resolve-release/scripts/durable-processing.mjs +0 -522
  129. package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +0 -659
  130. package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +0 -1014
  131. package/skills/engineering/resolve-release/scripts/finalize-release.mjs +0 -526
  132. package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +0 -169
  133. package/skills/engineering/resolve-release/scripts/green-gate.mjs +0 -599
  134. package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +0 -752
  135. package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +0 -56
  136. package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +0 -1538
  137. package/skills/engineering/resolve-release/scripts/postmortem.mjs +0 -381
  138. package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +0 -510
  139. package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +0 -326
  140. package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +0 -272
  141. package/skills/engineering/resolve-release/scripts/report.mjs +0 -417
  142. package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +0 -114
  143. package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +0 -238
  144. package/skills/engineering/resolve-release/scripts/review-packet.mjs +0 -503
  145. package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +0 -263
  146. package/skills/engineering/resolve-release/scripts/version-assert.mjs +0 -339
  147. package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +0 -485
  148. package/skills/engineering/resolve-release/scripts/version.mjs +0 -1199
  149. package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +0 -449
  150. package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +0 -21
  151. package/skills/engineering/resolve-release/vendor/README.md +0 -60
  152. package/skills/engineering/resolve-release/vendor/acorn.mjs +0 -6233
  153. package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +0 -21
  154. package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +0 -341
  155. package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +0 -70
  156. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +0 -2
  157. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +0 -1
  158. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +0 -7
  159. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +0 -1
  160. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +0 -2033
  161. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +0 -2033
  162. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +0 -7
  163. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +0 -1
  164. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +0 -2
  165. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +0 -1
  166. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +0 -2
  167. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +0 -1
  168. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +0 -2
  169. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +0 -1
  170. package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +0 -49
  171. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +0 -21
  172. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +0 -5
  173. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +0 -549
  174. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +0 -549
  175. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +0 -2
  176. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +0 -1
  177. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +0 -2
  178. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +0 -1
  179. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +0 -36
  180. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +0 -47
  181. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +0 -82
  182. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +0 -11
  183. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +0 -22
  184. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +0 -21
  185. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +0 -21
  186. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +0 -11
  187. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +0 -11
  188. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +0 -25
  189. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
  190. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +0 -85
  191. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +0 -85
  192. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +0 -2
  193. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +0 -1
  194. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +0 -2
  195. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +0 -1
  196. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +0 -20
  197. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +0 -20
  198. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +0 -2
  199. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +0 -1
  200. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +0 -2
  201. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +0 -1
  202. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +0 -61
  203. /package/skills/{engineering/resolve-issues → payment/tld-detection}/LICENSE +0 -0
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: tld-detection
3
+ description: >
4
+ Explicit-only. Potential TLD (transaction-laundering) clusters from
5
+ descriptor partitions, then exact currency-amount pairs, with same-descriptor
6
+ baseline contrasts, high/medium/low risk tiers, exposure sizing, and a
7
+ ≤3-sentence decision.
8
+ Not payment-analysis or fraud-analysis.
9
+ disable-model-invocation: true
10
+ ---
11
+
12
+ # TLD Detection
13
+
14
+ Find **potential TLD clusters** in an authorization extract. TLD here is
15
+ transaction laundering, not a domain name: hidden activity stuffed under a
16
+ normal MCC, often mixed across descriptors.
17
+
18
+ First partition the cleaned authorizations by **descriptor**. Inside each
19
+ descriptor, the clustering key is the **currency-amount-pair**. Geometric
20
+ relationships between exact anchors are the stuffing signal (掺量). BIN
21
+ country is not a membership key; report it in the cluster-versus-baseline
22
+ comparison after membership is frozen.
23
+
24
+ **Produce:** cluster results and a separate run-specific methodology document
25
+ under `reports/tld-detection/`.
26
+ **Do not produce:** confirmed laundering, a legal finding, or supervised
27
+ fraud-rule packages (`fraud-analysis`).
28
+
29
+ Paths under `references/` are relative to this skill.
30
+
31
+ ## Workflow
32
+
33
+ Follow these steps in order. Detail:
34
+ [references/workflow.md](references/workflow.md).
35
+
36
+ | Step | Do | Gate |
37
+ |---|---|---|
38
+ | 0 Pre-flight | File, grain, columns, window | Stop if auth grain, descriptor, amount, or currency column is missing; caption missing BIN country |
39
+ | 1 Clean | Dedup | Record drop counts; do not filter BIN country |
40
+ | 2 Cluster | Partition; rank pairs; identify anchors; freeze exact keys; compare with same-descriptor baseline | Partition = descriptor; ≥3 levels; adjacent levels = 2x; ≥100 attempts; absolute residual cap per candidate currency |
41
+ | 3 Risk | Assign high/medium/low investigation priority | Mixed BIN countries are neutral; exact 100% single-country concentration is a standout |
42
+ | 4 Decision | Conclusion + basis for the book | ≤3 sentences; no new evidence |
43
+ | 5 Report | Answer highest-risk, cluster-characteristic, and exposure questions; write + proofread | Sort high → medium → low; no confirmed-TLD wording |
44
+
45
+ ### 0 — Pre-flight
46
+
47
+ Authorization extract, one row per auth attempt. Record paths, time field,
48
+ amount, currency, BIN/issuer country, descriptor, MCC, response. Grain and
49
+ column aliases: [workflow.md](references/workflow.md).
50
+
51
+ ### 1 — Clean
52
+
53
+ [references/clean.md](references/clean.md). Deduplicate first. Do not
54
+ FX-convert the clustering key. Do not drop non-US BIN rows.
55
+
56
+ ### 2 — Cluster
57
+
58
+ [references/clustering.md](references/clustering.md). Build normalized
59
+ descriptor partitions, then rank currency-amount-pairs inside each descriptor. Use
60
+ `scripts/detect_ladders.py` to detect geometric anchor relationships with
61
+ adjacent, currency-specific absolute residual caps. Every cluster must contain
62
+ at least three theoretical levels with a fixed 2x relationship between adjacent
63
+ levels (for example 1x, 2x, 4x, 8x); search both up and down from every candidate
64
+ seed. A theoretical level may
65
+ keep multiple exact anchors, but each additional anchor must clear the stated
66
+ portfolio support floor. Freeze membership by exact descriptor, currency,
67
+ and amount; keep only clusters with ≥100 authorization attempts. Compare each
68
+ cluster with the baseline formed by removing that cluster from the same
69
+ descriptor. Do not invent clusters from MCC or comparison features.
70
+
71
+ ### 3 — Risk
72
+
73
+ [references/decision.md](references/decision.md). Assign every identified
74
+ currency-amount pair exactly one investigation-priority tier: High, Medium,
75
+ or Low. BIN-country mixture is neutral and never downgrades a cluster. Treat
76
+ an exact 100% single-BIN-country cluster as a standout; separately report the
77
+ cluster's share of that descriptor-country slice without using an arbitrary
78
+ coverage threshold or risk points.
79
+
80
+ ### 4 — Decision
81
+
82
+ Write the conclusion and the basis in **at most 3 sentences** for the whole
83
+ book. A one-line table per cluster is allowed under that.
84
+
85
+ ### 5 — Report
86
+
87
+ [references/report-template.md](references/report-template.md). Terms:
88
+ [references/terminology.md](references/terminology.md).
89
+
90
+ ```text
91
+ reports/tld-detection/<scope>_clusters.md
92
+ reports/tld-detection/<scope>_clusters.zh.md
93
+ reports/tld-detection/<scope>_clusters.zh.html
94
+ reports/tld-detection/<scope>_methodology.md
95
+ reports/tld-detection/<scope>_methodology.zh.md
96
+ reports/tld-detection/<scope>_methodology.zh.html
97
+ ```
98
+
99
+ Keep detection results in the cluster reports. Lead with the highest-risk
100
+ clusters, characterize every identified cluster and its descriptor share, then
101
+ quantify exposure by risk tier, descriptor, and across all authorization
102
+ attempts. Sort High → Medium → Low, then by evidence strength and attempts
103
+ inside each tier. Put the
104
+ actual run's cleaning, partitioning, parameter selection, sensitivity evidence,
105
+ baseline definition, and audit details in the methodology documents; link the
106
+ paired files in both directions. HTML is preferred when there are charts. Grep
107
+ banned strings after writing.
108
+
109
+ ## Progress
110
+
111
+ Track a task plan. One item is `in_progress` at a time.
112
+
113
+ 1. Pass pre-flight
114
+ 2. Freeze cleaned universe and descriptor partitions
115
+ 3. Assign High / Medium / Low risk tiers
116
+ 4. Publish descriptor currency-amount pairs + same-descriptor baselines
117
+ 5. Write ≤3-sentence decision
118
+ 6. Write report + separate run methodology and proofread
119
+
120
+ ## Boundary
121
+
122
+ | Need | Skill |
123
+ |---|---|
124
+ | Potential TLD clusters, currency-amount pairs, stuffing / 掺量, MCC miscoding, descriptor mixing | `tld-detection` |
125
+ | Volume, journey Sankey, auth rate, decline mix, settlement overview | `payment-analysis` |
126
+ | Proxy/confirmed fraud labels, holdout precision/recall, rule packages | `fraud-analysis` |
127
+
128
+ A suspected-fraud *rate contrast* in this skill is not a fraud-analysis
129
+ rule package.
130
+
131
+ ## Reference index
132
+
133
+ | Need | Read |
134
+ |---|---|
135
+ | Grain, columns, window | [workflow.md](references/workflow.md) |
136
+ | Dedup | [clean.md](references/clean.md) |
137
+ | Currency-amount pairs, anchors, same-descriptor baseline | [clustering.md](references/clustering.md) |
138
+ | ≤3-sentence conclusion | [decision.md](references/decision.md) |
139
+ | Report chapters | [report-template.md](references/report-template.md) |
140
+ | Language / banned strings | [terminology.md](references/terminology.md) |
141
+
142
+ ## Sanity check
143
+
144
+ - [ ] Auth grain; dedup counts are stated; no BIN-country row filter
145
+ - [ ] Partition key is normalized descriptor; missing descriptor is an explicit bucket
146
+ - [ ] Clustering key is original currency + amount, not USD
147
+ - [ ] Each rung-pool currency has an explicit adjacent absolute-residual cap and sensitivity evidence
148
+ - [ ] Multi-anchor levels state their portfolio support floor; final membership uses exact selected amount keys
149
+ - [ ] Cluster attempts ≥100
150
+ - [ ] Every cluster has a High / Medium / Low risk tier and results sort in that order
151
+ - [ ] Currency-amount pairs show seed and representative anchors; `*` marks a multi-amount level
152
+ - [ ] Same amount pair may recur across descriptor partitions; never merge them automatically
153
+ - [ ] BIN country is post-membership reporting data, not a membership key; Mixed is neutral
154
+ - [ ] Exact 100% single-country concentration is a standout; descriptor-country coverage is shown without a risk threshold
155
+ - [ ] Each cluster baseline is the same descriptor after removing that cluster
156
+ - [ ] Definition summary contains only descriptor, seed, anchors, and attempts
157
+ - [ ] Anchor table reports attempts, authorization success rate, and suspected-fraud share for every level, including n < 30
158
+ - [ ] Characteristics contain descriptor total, cluster attempts/share, MCC, and cluster-vs-baseline auth rate, suspected-fraud share, top 3 banks, and top 3 BIN countries
159
+ - [ ] Decision prose is ≤3 sentences (conclusion + basis)
160
+ - [ ] Report answers highest-risk, identified-cluster characteristics, and by-tier/by-descriptor exposure
161
+ - [ ] Run-specific methodology is separate from results; report and methodology link to each other
162
+ - [ ] Zero families → ranking only; no descriptor-invented clusters
163
+ - [ ] Language matches terminology.md; no confirmed-laundering claim
@@ -0,0 +1,9 @@
1
+ interface:
2
+ display_name: "TLD Detection"
3
+ short_description: "Risk-tiered TLD clusters from exact currency-amount pairs"
4
+
5
+ policy:
6
+ # Codex counterpart to SKILL.md disable-model-invocation: true
7
+ # (Claude Code / Pi). Keeps explicit invoke; blocks description-based
8
+ # auto-selection.
9
+ allow_implicit_invocation: false
@@ -0,0 +1,107 @@
1
+ {
2
+ "skill_name": "tld-detection",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "We think some merchants are stuffing TLD volume through a normal MCC. Authorizations_2026-03.csv has descriptors, MCC, BIN country, amount, currency, timestamp, and response codes. Find potential TLD clusters.",
7
+ "expected_output": "Deduplicates auths without a US-BIN filter; partitions by normalized descriptor; detects exact currency-amount pairs with explicit absolute residual caps; freezes membership; compares each cluster with the same descriptor after removing that cluster; assigns High, Medium, or Low investigation priority; and quantifies exposure by risk tier and descriptor.",
8
+ "expectations": [
9
+ "Uses normalized descriptor as the partition key and does not use BIN country as a membership key.",
10
+ "Uses adjacent currency-specific absolute residual caps with sensitivity evidence and no percentage tolerance.",
11
+ "Requires at least three theoretical levels with a fixed 2x relationship between adjacent levels.",
12
+ "Reports only currency-amount pairs with at least 100 exact-member attempts and compares each with the same descriptor after removing that cluster.",
13
+ "Reports Top 3 issuing banks and BIN countries only after membership is frozen.",
14
+ "Assigns every identified cluster High, Medium, or Low risk without treating the tier as confirmation of TLD.",
15
+ "Sorts results High to Medium to Low and reports exact-member exposure separately by tier and descriptor.",
16
+ "Keeps run-specific methodology in a separate linked document.",
17
+ "Provides a Verdict of at most three sentences without confirmed-laundering language."
18
+ ]
19
+ },
20
+ {
21
+ "id": 2,
22
+ "prompt": "Same descriptor seems to mix several ticket sizes that look like 9.99, 19.99, 39.99, 79.99. Another TLD name might be split across three billing descriptors. Cluster the book and tell me if those patterns hold.",
23
+ "expected_output": "Builds descriptor partitions and identifies qualifying currency-amount pairs independently inside them using at least three theoretical levels and a fixed 2x relationship; matching amounts across descriptors never merge membership.",
24
+ "expectations": [
25
+ "Builds descriptor partitions before currency-amount pairs.",
26
+ "Requires at least three theoretical levels and rejects non-2x relationships.",
27
+ "Requires at least 100 exact-member attempts before reporting a cluster.",
28
+ "Reports materially different currency-amount pairs under one descriptor.",
29
+ "Assesses MCC fit without calling a descriptor fabricated."
30
+ ]
31
+ },
32
+ {
33
+ "id": 3,
34
+ "prompt": "For each detected currency-amount pair, compare its behavior with the rest of the same descriptor.",
35
+ "expected_output": "Keeps BIN country out of the membership key, freezes exact membership, builds a same-descriptor baseline by removing only that cluster, compares the required rates and Top 3 dimensions, reports both BIN-country conditional shares, and charts transaction date and BIN-country local-hour distributions against that baseline.",
36
+ "expectations": [
37
+ "Does not partition detection by BIN country.",
38
+ "Uses the same descriptor after removing the current cluster as baseline.",
39
+ "Reports authorization success rate and suspected fraud as a share of attempts for Cluster and Baseline.",
40
+ "In each cluster definition, the anchor table reports attempts, authorization success rate, and suspected-fraud share for every theoretical level, including levels with fewer than 30 attempts.",
41
+ "For each Top 3 cluster BIN country, reports its share of the cluster and the cluster's share of all attempts in the same descriptor-country slice.",
42
+ "Treats exact 100% single-country concentration as a standout, Mixed as neutral, and country-slice coverage as descriptive without a risk threshold.",
43
+ "Charts transaction-date and BIN-country local-hour shares for Cluster and Baseline, normalizing each series independently."
44
+ ]
45
+ },
46
+ {
47
+ "id": 4,
48
+ "prompt": "Inside descriptor ACME, USD 10.00 is followed by 19.99 with 180 attempts, 20.00 with 40 attempts, and then 39.99. Build the potential TLD ladders.",
49
+ "expected_output": "Uses an explicit USD adjacent absolute residual cap; selects a primary exact anchor deterministically; may retain another exact anchor at the same theoretical level only if it clears the stated multi-anchor support floor; and applies exact descriptor, currency, and amount membership afterward.",
50
+ "expectations": [
51
+ "Runs ladder discovery only inside descriptor ACME.",
52
+ "Uses absolute adjacent residuals rather than percentage matching.",
53
+ "Selects the highest-count candidate as the primary anchor.",
54
+ "Retains an additional anchor only when it independently clears the declared support floor.",
55
+ "Never assigns every amount in a tolerance interval to the ladder."
56
+ ]
57
+ },
58
+ {
59
+ "id": 5,
60
+ "prompt": "Inside one descriptor I see an approximate EUR x2 amount pattern, but its selected exact amount keys total only 96 authorization attempts. Should it be reported?",
61
+ "expected_output": "Does not report the 96-attempt family; records it below threshold, keeps its transactions outside reported clusters, publishes its ranking, and does not invent a cluster from MCC or comparison features.",
62
+ "expectations": [
63
+ "Does not report the 96-attempt family.",
64
+ "Keeps its rows outside reported clusters.",
65
+ "Does not invent a cluster from comparison features.",
66
+ "Still provides a no-ladder Verdict of at most three sentences."
67
+ ]
68
+ },
69
+ {
70
+ "id": 6,
71
+ "prompt": "Descriptors ALPHA and BETA both have the exact USD 9.99, 19.99, 39.99 ladder with over 100 attempts, across several BIN countries. Should those transactions become one cluster?",
72
+ "expected_output": "Creates two descriptor-local currency-amount pairs, permits the same exact amounts in both descriptors, keeps their membership and same-descriptor baselines separate, and reports each independently.",
73
+ "expectations": [
74
+ "Creates two ladders because descriptor is the partition boundary.",
75
+ "Permits the same exact pairs in different descriptor ladders.",
76
+ "Does not merge matching fingerprints across descriptors.",
77
+ "Does not merge membership, metrics, or baselines.",
78
+ "Treats BIN country as post-membership reporting data."
79
+ ]
80
+ },
81
+ {
82
+ "id": 7,
83
+ "prompt": "USD 14.xx amounts are representative, but one percentage tolerance becomes too wide at larger amounts. Detect the ladders without sweeping a numeric interval into membership.",
84
+ "expected_output": "Runs a documented absolute-cap sensitivity grid, uses a currency-specific adjacent residual cap, searches every descriptor-local rung-pool seed, allows only sufficiently supported exact multi-anchors, rejects upper rungs outside the absolute cap, and freezes exact membership before BIN-country attribution.",
85
+ "expectations": [
86
+ "Does not use a percentage tolerance.",
87
+ "Reports the tested cap grid and selected cap.",
88
+ "Uses finite exact anchor sets with a stated multi-anchor support floor.",
89
+ "Rejects an upper rung whose adjacent residual exceeds the cap.",
90
+ "Computes BIN-country reporting values only after exact membership is frozen."
91
+ ]
92
+ },
93
+ {
94
+ "id": 8,
95
+ "prompt": "One cluster is 100% US BIN and covers 21.3% of its descriptor's US BIN attempts. Another is mixed and covers 33.8% of one descriptor-country slice. Grade and order the risk.",
96
+ "expected_output": "Treats the exact 100% single-country concentration as a standout and uses 21.3% only to explain its scale; treats Mixed as neutral and 33.8% as descriptive rather than a threshold; combines independent structural and behavioral evidence; assigns High, Medium, or Low risk; and sorts High to Medium to Low.",
97
+ "expectations": [
98
+ "Does not classify Mixed as Weak or automatically lower its risk tier.",
99
+ "Does not infer risk from a 20%, 33.8%, or other country-slice coverage threshold.",
100
+ "Requires exact 100% single-country composition for the BIN-country standout.",
101
+ "Reports cluster composition and descriptor-country slice coverage as separate conditional percentages.",
102
+ "Uses at least one independent corroborating characteristic before making a 100% single-country cluster High risk.",
103
+ "Preserves stable cluster IDs while sorting High to Medium to Low."
104
+ ]
105
+ }
106
+ ]
107
+ }
@@ -0,0 +1,51 @@
1
+ # Data cleaning
2
+
3
+ Run on the authorization extract before any clustering. Record every drop
4
+ count in the report appendix.
5
+
6
+ Do not filter to US-BIN here. Issuer country remains available for the
7
+ cluster-versus-baseline Top 3 BIN-country comparison.
8
+
9
+ ## 1. Exact-row dedup
10
+
11
+ Drop bitwise-duplicate rows (same values in every column used). Count
12
+ them. They are extract artefacts, not extra attempts.
13
+
14
+ ## 2. Identity dedup
15
+
16
+ If `Transaction ID` / `Auth ID` is unique when present, keep one row per
17
+ id (first by time).
18
+
19
+ Otherwise, if `Order ID` is present, keep one row per
20
+ (`Order ID`, time, amount, currency, masked PAN / last4 if present).
21
+ Retries of the same order at different times stay distinct.
22
+
23
+ If none of those identities exist, **skip this step** — keep the
24
+ exact-row-deduped table and say identity-dup was skipped. Do not stop
25
+ the run. Do not invent a customer id from BIN + amount.
26
+
27
+ ## 3. Amount and currency
28
+
29
+ - Clustering key uses the **original** amount and currency.
30
+ - Normalize `10`, `10.0`, `10.00` to the same decimal key.
31
+ - Drop rows with missing amount or currency; count them.
32
+ - Do not FX-convert before clustering. A 9.99 EUR rung is not a 9.99 USD
33
+ rung. Amount sums later stay inside one currency; never add EUR to USD.
34
+
35
+ ## 4. Missing dimensions
36
+
37
+ Rows with missing descriptor or BIN / issuer country stay in the
38
+ clustering universe. Missing descriptors enter the `UNKNOWN_DESCRIPTOR`
39
+ partition; missing countries enter the `UNKNOWN_BIN_COUNTRY` reporting
40
+ bucket after membership is frozen.
41
+
42
+ ## Output of this step
43
+
44
+ A cleaned table plus a one-line census:
45
+
46
+ ```
47
+ raw N → exact-dup drop n1 → identity-dup drop n2 (or skipped)
48
+ → missing amount/currency n3 → cleaned universe U
49
+ ```
50
+
51
+ All later attempt counts use `U`, not `raw N`.
@@ -0,0 +1,219 @@
1
+ # Currency-amount-pair clustering
2
+
3
+ Goal: partition the cleaned universe by descriptor, find stuffing (掺量)
4
+ as **approximate geometric ladders** inside each descriptor, then decompose
5
+ each qualifying ladder into BIN-country attribution components and contrast
6
+ it against the remainder.
7
+
8
+ ## Descriptor partition
9
+
10
+ Partition key = `normalized descriptor`.
11
+
12
+ - Trim, case-fold, and collapse repeated whitespace. Preserve the most
13
+ frequent source spelling for display.
14
+ - Do not fuzzy-match or strip dynamic suffixes unless the extract documents
15
+ their semantics.
16
+ - Use `UNKNOWN_DESCRIPTOR` for missing values; do not drop them.
17
+
18
+ Freeze descriptor assignment before ranking amounts. Report each descriptor's
19
+ attempt count and share of `U`. A ladder belongs to exactly one descriptor;
20
+ the same exact currency-amount-pair may legitimately belong to ladders in
21
+ different descriptors.
22
+
23
+ BIN country is **not** a partition or membership key. Normalize it after
24
+ ladder formation and report its attempt counts, shares, auth rates, suspected-
25
+ fraud rates, and local-hour shapes as attribution components.
26
+
27
+ ## Currency-amount-pair
28
+
29
+ Key = (`currency`, `amount`) on the original (not FX-converted) amount.
30
+
31
+ Count = authorization **attempts** in the current partition. Rank
32
+ descending by count. Ties: smaller amount first, then currency code.
33
+
34
+ ## High-count set and rung pool
35
+
36
+ Work **per partition, then per currency**. In the table below, `|P|` is
37
+ the authorization-attempt count of the current partition.
38
+
39
+ | Set | Membership |
40
+ |---|---|
41
+ | High-count (seeds) | union of (a) pairs with count ≥ `max(30, 0.5% of \|P\|)` (b) the partition top 25 pairs by count (c) per currency in the partition, the top 10 pairs with count ≥ 30 |
42
+ | Rung pool | pairs with count ≥ `max(5, 0.1% of \|P\|)` |
43
+
44
+ State the thresholds. Use the high-count set for ranking. Test every rung-pool
45
+ pair as a possible seed for a three-level 2x relationship; otherwise a
46
+ representative lower-volume path can be structurally impossible to discover.
47
+ Extra levels may be quieter amounts in
48
+ the rung pool, and (c) keeps a smaller currency visible inside the partition.
49
+
50
+ If the rung pool has fewer than three pairs in every currency of a partition,
51
+ that partition has no three-level ladder to test. Still publish its ranking
52
+ table when it is among the largest partitions or has a below-threshold family.
53
+
54
+ ## Ladder detection
55
+
56
+ Ladder detection has two separate phases. **Discovery** uses an adjacent,
57
+ currency-specific absolute residual cap. **Membership and every downstream
58
+ metric use the exact descriptor plus selected currency-amount-pairs only.**
59
+ Never widen final membership to a numeric interval or another descriptor.
60
+
61
+ ### Adjacent absolute-residual rule
62
+
63
+ For exact amounts `a < b` in one descriptor and currency, multiplier `m` has:
64
+
65
+ ```text
66
+ residual = |b - a · m|
67
+ ```
68
+
69
+ They are adjacent anchors only when `residual ≤ ε_currency`. Do not use one
70
+ percentage tolerance across amounts: its absolute allowance grows with the
71
+ amount and can merge materially different upper-rung prices.
72
+
73
+ Configure and report one cap per currency represented in a partition's rung
74
+ pool. For a two-decimal currency, test a sensitivity grid such as `0.02,
75
+ 0.05, 0.10, 0.15, 0.25` and retain the smallest operationally justified cap
76
+ under which material paths are stable. Fail closed when a rung-pool currency
77
+ has no cap; currencies below the rung-pool threshold need no cap.
78
+
79
+ Use the bundled deterministic implementation after producing a cleaned
80
+ authorization CSV:
81
+
82
+ ```bash
83
+ python3 {baseDir}/scripts/detect_ladders.py cleaned-authorizations.csv \
84
+ --descriptor-column descriptor --bin-country-column bin_country \
85
+ --currency-column currency --amount-column amount \
86
+ --cap USD=0.15 --multi-anchor-min-attempts 24 \
87
+ --sensitivity-cap USD=0.02 --sensitivity-cap USD=0.05 \
88
+ --sensitivity-cap USD=0.10 --sensitivity-cap USD=0.15 \
89
+ --sensitivity-cap USD=0.25
90
+ ```
91
+
92
+ The CLI does not clean or deduplicate the CSV; complete
93
+ [clean.md](clean.md) first.
94
+
95
+ ### Family from a seed (up and down)
96
+
97
+ Starting from every rung-pool seed, expand recursively upward and downward
98
+ using only adjacent matches. A theoretical level may contain several exact
99
+ anchors. Select the highest-count match as its primary anchor; retain an
100
+ additional match only when that exact pair independently clears the stated
101
+ portfolio support floor (default 24 attempts, corresponding to the Worldpay
102
+ portfolio rung floor). Record that floor and test it separately for a new
103
+ portfolio.
104
+
105
+ Every retained key must be in the partition's rung pool and match an anchor
106
+ in the adjacent level. The finite retained keys become the explicit anchor
107
+ set. Tolerance never acts on transactions after selection: final membership
108
+ is exact equality on (`descriptor`, `currency`, `amount`). BIN country is
109
+ attached only after this membership is frozen.
110
+
111
+ ### Required 2x family
112
+
113
+ A candidate family must use **`m = 2`** between every adjacent theoretical
114
+ level and contain **at least three theoretical levels**. Example: 1x, 2x, 4x,
115
+ 8x around the seed, including downward (`19.99` can find `9.99` and `39.99`).
116
+ There is no two-level exception, and relationships based on `m = 3`, `4`, `5`,
117
+ `10`, or any other multiplier do not form clusters.
118
+
119
+ For each seed, rank qualifying paths by: more theoretical levels; more exact-
120
+ member attempts; then lower summed adjacent residual. The attempt threshold
121
+ below independently determines whether the family becomes a reported cluster.
122
+
123
+ ### Minimum cluster size
124
+
125
+ Sum attempts only over rows in the partition whose keys are the selected
126
+ exact currency-amount-pairs. A family is a reported cluster only when that
127
+ exact membership has **≥100 authorization attempts**. Keep smaller
128
+ families in the run methodology document as `below threshold`; do not validate them or
129
+ issue cluster verdicts for them. Their rows remain in canonical baseline
130
+ `B` and descriptor remainder `B_D` unless selected exact keys are claimed
131
+ by another reported ladder in the same descriptor.
132
+
133
+ ### Several groups
134
+
135
+ Within each partition, process unused rung-pool seeds in descending attempt
136
+ count. A currency-amount-pair joins **at most one** reported cluster in that
137
+ partition — the first qualifying family that claims it. Below-threshold
138
+ families do not reserve keys. Never let a claim in one partition reserve the
139
+ same pair in another partition.
140
+
141
+ Name clusters `C1`, `C2`, … by descending total attempts. For each, record
142
+ the descriptor partition, seed, currency, multiplier, absolute cap, summed
143
+ fit residual, theoretical levels, all exact anchors and counts, multi-anchor
144
+ levels, total attempts, and post-formation BIN-country components.
145
+
146
+ Ignore one-off round amounts (`100`, `1000`) unless they sit on a ladder.
147
+ A popular SKU price is not a cluster by itself.
148
+
149
+ ### None found
150
+
151
+ If no family qualifies in any partition, **do not invent clusters** from
152
+ MCC or comparison features. Publish the partition and pair rankings, contrast
153
+ the top pairs only as context if useful, and skip cluster verdicts.
154
+
155
+ ## Baseline
156
+
157
+ For each cluster, **Baseline** means every authorization in the same descriptor
158
+ after removing that cluster's exact member keys. Other identified
159
+ currency-amount pairs remain in this baseline. This is the only comparison
160
+ population used in cluster characteristics. If the cluster consumes the whole
161
+ descriptor, report comparison values as `n/a`.
162
+
163
+ For the overall impact table only, `Baseline` means rows in the cleaned universe
164
+ that belong to no identified currency-amount pair. Keep this distinct from the
165
+ per-cluster same-descriptor baseline.
166
+
167
+ If two currencies each have a ladder, they are separate clusters. Do not
168
+ merge across currencies.
169
+
170
+ ## Contrast vs baseline
171
+
172
+ Same window and descriptor. Compare each cluster with its baseline on:
173
+
174
+ | Metric | Formula |
175
+ |---|---|
176
+ | Authorization success rate | approvals / attempts |
177
+ | Suspected fraud as share of attempts | suspected-fraud attempts / attempts |
178
+ | Top 3 issuing banks | count and share of that series |
179
+ | Top 3 BIN countries | count and share of that series |
180
+
181
+ Separately report Descriptor, descriptor total attempts, cluster attempts,
182
+ cluster share of descriptor, and MCC.
183
+
184
+ Require a stated min-n before ranking a cluster-versus-baseline rate
185
+ (default attempts ≥ 30). Below that, show the contrast rate as `n/a (n=…)`.
186
+ The definition anchor table is not a ranking contrast: always compute
187
+ authorization success rate and suspected-fraud share for every theoretical
188
+ level from that level's exact member attempts, including n < min-n. Combined
189
+ `*` levels use the combined attempts of the level. Do not write `n/a` on the
190
+ anchor table because the rung is small.
191
+
192
+ Use the contrast to assign investigation-priority risk under
193
+ [decision.md](decision.md), not as a fraud label. Treat materially different
194
+ authorization, suspected-fraud, issuing-bank, date, and local-hour behavior as
195
+ independent characteristics under thresholds declared in the run methodology.
196
+
197
+ For each Top 3 cluster BIN country, report both its share of the cluster and
198
+ the cluster's share of all attempts in the same descriptor-country slice. An
199
+ exact 100% single-country cluster is a standout. `Mixed` is neutral, and
200
+ country-slice coverage is descriptive only: do not set a universal threshold
201
+ or award risk points for values such as 20% or 33.8%.
202
+
203
+ ## What not to do
204
+
205
+ - Do not treat MCC as a partition or clustering key.
206
+ - Do not discover ladders across descriptor boundaries.
207
+ - Do not use BIN country as a ladder partition or membership key.
208
+ - Do not k-means the amounts.
209
+ - Do not convert to USD and then look for ladders.
210
+ - Do not search only upward from the busiest rung.
211
+ - Do not use a percentage tolerance across amounts.
212
+ - Do not assign every amount inside an interval; select finite exact anchors first.
213
+ - Do not retain a low-support additional anchor merely because it is near a primary anchor.
214
+ - Do not report a cluster with fewer than three theoretical levels.
215
+ - Do not use any adjacent-level multiplier other than 2x.
216
+ - Do not report a cluster with fewer than 100 attempts.
217
+ - Do not put the same pair in two clusters within one partition.
218
+ - Do not merge matching amount fingerprints across descriptors.
219
+ - Do not call the output a customer segment or a marketing cohort.
@@ -0,0 +1,85 @@
1
+ # Risk decision
2
+
3
+ After currency-amount-pair detection and same-descriptor baseline comparison,
4
+ assign investigation-priority risk tiers. This is prioritization, not a finding
5
+ that transaction laundering occurred.
6
+
7
+ ## Eligibility versus risk
8
+
9
+ The cluster gate (at least three theoretical levels, fixed 2x adjacency, at
10
+ least 100 exact-member attempts) determines which currency-amount pairs enter
11
+ the result. Passing that gate does not by itself determine High, Medium, or Low
12
+ risk.
13
+
14
+ Risk uses independent post-membership evidence:
15
+
16
+ - structural strength beyond the minimum, such as a fourth or later level
17
+ - cluster share of its descriptor
18
+ - authorization-success and suspected-fraud differences versus the same-
19
+ descriptor baseline
20
+ - issuing-bank differences versus that baseline
21
+ - transaction-date and BIN-country-local-hour differences versus that baseline
22
+ - externally evidenced MCC or merchant-business mismatch; never infer this
23
+ from a suggestive descriptor name alone
24
+
25
+ Declare portfolio-specific thresholds for a materially different rate,
26
+ distribution, or descriptor share in the run methodology before assigning
27
+ risk. Do not invent universal cutoffs after seeing the results.
28
+
29
+ ## BIN-country evidence
30
+
31
+ BIN country is post-membership evidence, not a partition, membership key, or
32
+ veto. `Mixed` is neutral and must never reduce a risk tier by itself.
33
+
34
+ For every Top 3 cluster BIN country, report both conditional views:
35
+
36
+ ```text
37
+ cluster composition = cluster attempts in country / all cluster attempts
38
+ country-slice coverage = cluster attempts in country /
39
+ all attempts in the same descriptor and country
40
+ ```
41
+
42
+ An exact **100% single-BIN-country cluster** is a standout characteristic.
43
+ Country-slice coverage explains how large that concentration is inside the
44
+ descriptor-country population, but it has no fixed threshold and contributes
45
+ no independent risk points. Values such as 20% or 33.8% are descriptive, not
46
+ self-interpreting risk signals. Any value below 100% is not promoted merely
47
+ because it is numerically high.
48
+
49
+ ## Risk tiers
50
+
51
+ Assign exactly one tier to every identified currency-amount pair:
52
+
53
+ | Tier | Use when |
54
+ |---|---|
55
+ | High | An exact 100% single-country standout has at least one independent corroborating risk characteristic, or several independently strong non-country characteristics converge |
56
+ | Medium | At least two independent characteristics materially differ from the same-descriptor baseline, but High is not justified |
57
+ | Low | The structural cluster gate is met, but observed corroborating evidence is limited or not material |
58
+
59
+ Do not use a generic 0–100 score unless the business has approved and calibrated
60
+ its weights and cutoffs. Missing fields reduce confidence and must be disclosed;
61
+ they are not evidence that risk is Low.
62
+
63
+ Sort report results `High → Medium → Low`. Within a tier, sort by the number and
64
+ magnitude of independently supported characteristics, then by exact-member
65
+ attempts. Preserve stable cluster IDs when sorting an existing result.
66
+
67
+ ## Length and required content
68
+
69
+ The Verdict is at most three sentences for the whole book:
70
+
71
+ 1. State the highest risk tier found and that it is an investigative priority,
72
+ not confirmation that TLD occurred.
73
+ 2. For High-risk clusters, give descriptor, representative anchors, attempts,
74
+ descriptor share, standout evidence, and the clearest independent
75
+ corroborating characteristic.
76
+ 3. Give exact-member exposure by risk tier and as a share of all authorization
77
+ attempts.
78
+
79
+ If no currency-amount pair qualifies, state that none qualified, name the top
80
+ descriptor and candidate amounts, and report zero identified-cluster exposure.
81
+ Do not invent a cluster. Do not recommend filing a SAR, terminating a merchant,
82
+ or correcting an MCC.
83
+
84
+ First use of TLD is “transaction laundering (TLD)”. Proofread with
85
+ [terminology.md](terminology.md).