Setu · an archived project
The evidence
Setu looked for duplicate companies in Singapore's registry and found none. Every claim in the account is here, in a form you can check. Captured 2026-07-31 from the running system, on its last day.
What the detector actually scored
The detector flagged 58 candidate duplicate pairs. Where both companies carried an ACRA identifier, the pair could be settled outright: two different registry identifiers means two different legal entities, with no judgement required.
| Band | Precision | Wilson LB | Decisive (true/false) | Unmeasurable |
|---|---|---|---|---|
| fuzzy | 0.000 | 0.000 | 52 (0 / 52) | 2 |
| normalized name | 0.000 | 0.000 | 1 (0 / 1) | 3 |
Zero true positives over 53 decisive pairs. Five more had no anchor on both sides and are reported separately rather than folded in, because a number that quietly absorbs its own unmeasurable cases is not a measurement.
The publish gate read both bands as closed and published nothing, across the
whole run. The public precision figure stayed at unmeasured by design.
The council, and what the summary could not tell me
174 verdicts across 58 pairs, from two vendors. A merge required both vendor families to agree independently; an abstention from either blocked it.
| Role | Model | Merge | Keep apart | Abstain |
|---|---|---|---|---|
| proposer | claude-sonnet-4-6 | 4 | 53 | 1 |
| skeptic | deepseek-v4-pro | 0 | 50 | 8 |
| judge | claude-sonnet-4-6 | 4 | 53 | 1 |
Zero merges executed. On all four pairs where proposer and judge argued to merge, the skeptic abstained with a parse failure — output the client could not read. Not one of the four was stopped by a reasoned objection. Proposer and judge are the same vendor; the independent second opinion never arrived on any pair that mattered.
This is what a working case looks like, where the skeptic did return a verdict:
And this is what all four merge candidates looked like:
abstain: MemberOutputError
Do former names need a third-party index?
Searching UNITED OVERSEAS LAND on the official registry portal on 2026-07-31
returned:
Formerly known as
UNITED OVERSEAS LAND LIMITED
UEN 196300438C · Live Company
No. The registrar resolves former names itself and labels them in the result. The 101,501-name index Setu carried was redundant for its whole life.
How much fuzzy matching the procurement join needed
All 18,464 government procurement awards, reduced to 6,151 distinct supplier names, sampled at random with a fixed seed.
matched a registered company exactly — 393 of 500, 95% confidence interval 74.8 to 82.0. Normalising punctuation and legal suffixes recovered none of the 107 misses. Relaxing to trigram similarity produced candidates, and inspection of the candidates is the finding:
| Similarity | Supplier | Nearest registered company |
|---|---|---|
| 0.833 | SP CONSULTANCY | SP HR CONSULTANCY |
| 0.800 | KAK SOLUTIONS PTE. LTD. | KARA SOLUTIONS PTE. LTD. |
| 0.762 | ANTHOLOGY INTERNATIONAL PRIVATE LIMITED | ANZ INTERNATIONAL PRIVATE LIMITED |
| 0.711 | BLACKPEAK (SINGAPORE) PTE. LIMITED | BLACKBERRY SINGAPORE PTE. LIMITED |
| 0.688 | TAN BOON KEE | TAN BOON KENG |
Lowering the threshold does not recover true matches here. It manufactures false ones — the same failure the anchor measurement found on the registry, reached from an unrelated direction. The misses are individuals, foreign companies, sole traders and entities since struck off. They have no counterpart to match against.
Every assumption that went unchecked
| The assumption | Cost to check | What it was |
|---|---|---|
| The registry holds duplicates worth detecting | one report | 53 checkable pairs, 53 different companies, 0 duplicates |
| The registrar cannot search former names | five minutes | It can, and it prints the former name in the result |
| Zero merges proved the adversarial design worked | one query | 4 of 4 blocked by a parse failure, not by an argument |
| The unmatched suppliers need fuzzy matching | one scan | Similarity returns BLACKPEAK/BLACKBERRY; there is nothing to match to |
| 46 of 48 suppliers match | one seeded sample | 78.6%; the first sample was the head of the table |
| The misses match at no similarity threshold | one measurement | Wrong as stated; 8 of 107 exceed 0.7 |
| A phantom row came from names with line breaks | one raw dump | No. The fix was a no-op and the result was byte-identical |
| Then it came from supplier names with line breaks | one query | No. It was a database client status line counted as data |
The last four happened on the day the account was written, two of them while correcting the other two.
Decisions, including the one that warned me
Twenty-four decision records were written as the work happened, with the rejected options kept alongside the chosen one. Four are worth reading against what followed.
ADR-0015 — the quality oracle. Rejected "council consensus is the quality signal" on the grounds that it is self-certification with correlated blind spots. It states that consensus is not correctness. I then took the council's zero merges as evidence the design worked, without reading the transcripts, which is precisely the error this record rejects. The architecture was right and I did not follow it.
ADR-0018 — the publish gate. Rejected putting the precision thresholds in environment configuration, on the grounds that a live unattended publisher must not be able to have its own bar lowered. Safety policy stays in versioned code. This one held.
ADR-0010 — the resolver. Rejected auto-merging high-confidence pairs to cut review load, because there was no measured precision yet: surface, measure, then graduate. Had this gone the other way, the system would have merged 53 pairs of unrelated companies.
ADR-0014 — the council. Rejected a single model and same-family majority vote, requiring two vendors to concur on a destructive action. The design was sound; the failure was that a vendor going silent looks identical to a vendor agreeing, unless you read the transcript.
The raw material
Every file the numbers above came from. Checksums are in the manifest.
- council-transcripts.json — all 174 verdicts with full reasoning
- gebiz-match-rate.md — method, result, and the limits of the claim
- gebiz-similarity-check.json — best-similarity per miss, and the correction
- bizfile-former-name-test.md — the five-minute test, verbatim
- db-census.md — every count, taken from the running database
- metrics-2026-07-31.txt — the final metrics scrape
- MANIFEST.md — checksums for all of it
Counts describing the registry snapshot are as captured between 2026-07-14 and 2026-07-31. The ingest never removed entities that stopped being Live, so the entity count is an upper bound. Source: ACRA via data.gov.sg, under the Singapore Open Data Licence.