@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.
- package/README.md +9 -4
- package/package.json +1 -1
- package/runtime/skills/distribution/generated/recipes.json +54 -48
- package/runtime/skills/distribution/scripts/bundles.mjs +113 -7
- package/runtime/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
- package/runtime/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
- package/skills/cicd-pipeline/mergify/SKILL.md +1 -1
- package/skills/engineering/engineering-runtime/coherence/workflow.json +14 -83
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
- package/skills/engineering/smoke/SKILL.md +1 -1
- package/skills/payment/payment-analysis/SKILL.md +13 -7
- package/skills/payment/payment-analysis/references/chargebacks.md +43 -18
- package/skills/payment/payment-analysis/references/event-layers.md +4 -0
- package/skills/payment/payment-analysis/references/metrics.md +9 -7
- package/skills/payment/payment-analysis/references/report-template.md +3 -3
- package/skills/payment/payment-analysis/references/terminology.md +6 -1
- package/skills/payment/payment-analysis/references/visualization.md +1 -1
- package/skills/payment/tld-detection/SKILL.md +163 -0
- package/skills/payment/tld-detection/agents/openai.yaml +9 -0
- package/skills/payment/tld-detection/evals/evals.json +107 -0
- package/skills/payment/tld-detection/references/clean.md +51 -0
- package/skills/payment/tld-detection/references/clustering.md +219 -0
- package/skills/payment/tld-detection/references/decision.md +85 -0
- package/skills/payment/tld-detection/references/report-template.md +169 -0
- package/skills/payment/tld-detection/references/terminology.md +69 -0
- package/skills/payment/tld-detection/references/workflow.md +78 -0
- package/skills/payment/tld-detection/scripts/detect_ladders.py +390 -0
- package/skills/payment/tld-detection/tests/test_detect_ladders.py +132 -0
- package/skills/engineering/resolve-issues/SKILL.md +0 -168
- package/skills/engineering/resolve-issues/agents/openai.yaml +0 -9
- package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +0 -499
- package/skills/engineering/resolve-issues/references/breaker.md +0 -82
- package/skills/engineering/resolve-issues/references/deliverables.md +0 -27
- package/skills/engineering/resolve-issues/references/delivery.md +0 -108
- package/skills/engineering/resolve-issues/references/evidence-lane.md +0 -21
- package/skills/engineering/resolve-issues/references/exact-head-ci.md +0 -287
- package/skills/engineering/resolve-issues/references/fan-out.md +0 -33
- package/skills/engineering/resolve-issues/references/finalization.md +0 -68
- package/skills/engineering/resolve-issues/references/guarantees.md +0 -10
- package/skills/engineering/resolve-issues/references/high-risk.md +0 -29
- package/skills/engineering/resolve-issues/references/incidents/848/README.md +0 -156
- package/skills/engineering/resolve-issues/references/intake.md +0 -86
- package/skills/engineering/resolve-issues/references/integration-gate.md +0 -53
- package/skills/engineering/resolve-issues/references/interference.md +0 -87
- package/skills/engineering/resolve-issues/references/loop.md +0 -134
- package/skills/engineering/resolve-issues/references/model-catalog.md +0 -9
- package/skills/engineering/resolve-issues/references/postmortem.md +0 -27
- package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +0 -41
- package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +0 -48
- package/skills/engineering/resolve-issues/references/pre-flight.md +0 -41
- package/skills/engineering/resolve-issues/references/regression-checklist.md +0 -26
- package/skills/engineering/resolve-issues/references/run-state.md +0 -288
- package/skills/engineering/resolve-issues/references/sandboxed-testing.md +0 -48
- package/skills/engineering/resolve-issues/references/spawn-contract.md +0 -96
- package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +0 -40
- package/skills/engineering/resolve-issues/references/why.md +0 -653
- package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +0 -49
- package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +0 -721
- package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +0 -962
- package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +0 -220
- package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +0 -420
- package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +0 -256
- package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +0 -168
- package/skills/engineering/resolve-issues/scripts/discover-models.mjs +0 -9
- package/skills/engineering/resolve-issues/scripts/doctrine.mjs +0 -62
- package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +0 -191
- package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +0 -413
- package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +0 -332
- package/skills/engineering/resolve-issues/scripts/finalize.mjs +0 -488
- package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +0 -3307
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +0 -16
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +0 -51
- package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +0 -17
- package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +0 -166
- package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +0 -92
- package/skills/engineering/resolve-issues/scripts/guide-index.mjs +0 -73
- package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +0 -159
- package/skills/engineering/resolve-issues/scripts/interference.mjs +0 -427
- package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +0 -9
- package/skills/engineering/resolve-issues/scripts/next-operations.mjs +0 -419
- package/skills/engineering/resolve-issues/scripts/postmortem.mjs +0 -909
- package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +0 -345
- package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +0 -415
- package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +0 -697
- package/skills/engineering/resolve-issues/scripts/report.mjs +0 -494
- package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +0 -172
- package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +0 -79
- package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +0 -334
- package/skills/engineering/resolve-issues/scripts/run-state.mjs +0 -4792
- package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +0 -395
- package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +0 -290
- package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +0 -170
- package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +0 -293
- package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +0 -197
- package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +0 -127
- package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +0 -893
- package/skills/engineering/resolve-issues/scripts/workspaces.mjs +0 -829
- package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +0 -290
- package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +0 -80
- package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +0 -102
- package/skills/engineering/resolve-release/LICENSE +0 -3
- package/skills/engineering/resolve-release/SKILL.md +0 -113
- package/skills/engineering/resolve-release/agents/openai.yaml +0 -9
- package/skills/engineering/resolve-release/references/assembly.md +0 -137
- package/skills/engineering/resolve-release/references/auto-when-green.md +0 -56
- package/skills/engineering/resolve-release/references/candidate.md +0 -167
- package/skills/engineering/resolve-release/references/exposure.md +0 -178
- package/skills/engineering/resolve-release/references/handoff.md +0 -24
- package/skills/engineering/resolve-release/references/postmortem.md +0 -230
- package/skills/engineering/resolve-release/references/preflight.md +0 -208
- package/skills/engineering/resolve-release/references/principles.md +0 -94
- package/skills/engineering/resolve-release/references/regression-checklist.md +0 -36
- package/skills/engineering/resolve-release/references/related-skills.md +0 -13
- package/skills/engineering/resolve-release/references/routing.md +0 -149
- package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +0 -285
- package/skills/engineering/resolve-release/references/versioning.md +0 -202
- package/skills/engineering/resolve-release/references/why.md +0 -53
- package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +0 -389
- package/skills/engineering/resolve-release/scripts/build-changes.mjs +0 -209
- package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +0 -407
- package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +0 -904
- package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +0 -81
- package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +0 -612
- package/skills/engineering/resolve-release/scripts/close-attempt.mjs +0 -135
- package/skills/engineering/resolve-release/scripts/closeout-release.mjs +0 -161
- package/skills/engineering/resolve-release/scripts/doctrine.mjs +0 -106
- package/skills/engineering/resolve-release/scripts/durable-processing.mjs +0 -522
- package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +0 -659
- package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +0 -1014
- package/skills/engineering/resolve-release/scripts/finalize-release.mjs +0 -526
- package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +0 -169
- package/skills/engineering/resolve-release/scripts/green-gate.mjs +0 -599
- package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +0 -752
- package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +0 -56
- package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +0 -1538
- package/skills/engineering/resolve-release/scripts/postmortem.mjs +0 -381
- package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +0 -510
- package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +0 -326
- package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +0 -272
- package/skills/engineering/resolve-release/scripts/report.mjs +0 -417
- package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +0 -114
- package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +0 -238
- package/skills/engineering/resolve-release/scripts/review-packet.mjs +0 -503
- package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +0 -263
- package/skills/engineering/resolve-release/scripts/version-assert.mjs +0 -339
- package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +0 -485
- package/skills/engineering/resolve-release/scripts/version.mjs +0 -1199
- package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +0 -449
- package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +0 -21
- package/skills/engineering/resolve-release/vendor/README.md +0 -60
- package/skills/engineering/resolve-release/vendor/acorn.mjs +0 -6233
- package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +0 -21
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +0 -341
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +0 -70
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +0 -7
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +0 -2033
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +0 -2033
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +0 -7
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +0 -49
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +0 -21
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +0 -5
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +0 -549
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +0 -549
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +0 -36
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +0 -47
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +0 -82
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +0 -11
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +0 -22
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +0 -21
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +0 -21
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +0 -11
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +0 -11
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +0 -25
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +0 -85
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +0 -85
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +0 -20
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +0 -20
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +0 -61
- /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).
|