edgepiityped character spans
taxonomy 2026.11 GitHub

Fifteen worked examples

Every span below came from the real library. The page is generated by site/gen_data.py and site/build.py, and the build fails if a single recorded offset breaks source[start:end] == text. There is no hand-written result on this page.

note
Every string is fake. Do not replace one with production text. Examples 10 to 14 need a model lane, because a name, an address, a national id, and a login name have no grammar a rule can own.

How to read a block

FieldMeaning
SourceYour string, with each span marked. Hover a mark for its offsets.
ResultThe span table. ok means the recorded slice equals the recorded text.
Score1.00 means a checksum confirmed the slice. — means no validator exists for that form.
MaskedThe same string with placeholders in place of spans.
VaultPlaceholder to original slice. A secret never appears here.

1 A support ticket

Lane rules · 1 × EMAIL, 1 × PAYMENT, 1 × PHONE

Three structured forms, each confirmed by a grammar or a checksum. Order 48291 is not PII, so it stays visible.

Source

Customer Ada Lovelace called from +852 5555 0101. Email ada@example.com. Card 4242424242424242. Order 48291.

Result

#TypeStartEndTextScoreSlice
1 PHONE3448+852 5555 0101—ok
2 EMAIL5671ada@example.com—ok
3 PAYMENT789442424242424242421.00ok

Masked output

Customer Ada Lovelace called from <PHONE_1>. Email <EMAIL_1>. Card <PAYMENT_1>. Order 48291.

Vault

PlaceholderValue
<PHONE_1>+852 5555 0101
<EMAIL_1>ada@example.com
<PAYMENT_1>4242424242424242

2 A note with a password

Lane rules · 1 × EMAIL, 1 × PHONE, 1 × SECRET

A secret is irreversible on purpose. Restoring it would write a password into the next system.

Source

Ask Ada Lovelace <ada@example.com> to call +1 202 555 0147 about ticket 77. Do not include the password hunter2 in the note.

Result

#TypeStartEndTextScoreSlice
1 EMAIL1833ada@example.com—ok
2 PHONE4358+1 202 555 01471.00ok
3 SECRET104111hunter2—ok

Masked output

Ask Ada Lovelace <<EMAIL_1>> to call <PHONE_1> about ticket 77. Do not include the password <SECRET> in the note.

Vault

PlaceholderValue
<EMAIL_1>ada@example.com
<PHONE_1>+1 202 555 0147

3 A wire transfer

Lane rules · 1 × EMAIL, 1 × IP_ADDRESS, 1 × PAYMENT

The IBAN passes the MOD-97 check. 4242424242424243 fails Luhn, so the rule refuses it rather than guessing.

Source

Wire to IBAN GB82WEST12345698765432 from card 4242424242424243. Reach ops at ops@example.org or 203.0.113.10.

Result

#TypeStartEndTextScoreSlice
1 PAYMENT1335GB82WEST123456987654321.00ok
2 EMAIL7792ops@example.org—ok
3 IP_ADDRESS96108203.0.113.101.00ok

Masked output

Wire to IBAN <PAYMENT_1> from card 4242424242424243. Reach ops at <EMAIL_1> or <IP_ADDRESS_1>.

Vault

PlaceholderValue
<PAYMENT_1>GB82WEST12345698765432
<EMAIL_1>ops@example.org
<IP_ADDRESS_1>203.0.113.10

4 A Chinese contact line

Lane rules · 1 × EMAIL, 1 × PHONE

The rule lane is language neutral for structured forms. The phone still passes libphonenumber.

Source

联系人张伟,手机13800138000,邮箱wei@example.com。

Result

#TypeStartEndTextScoreSlice
1 PHONE819138001380001.00ok
2 EMAIL2237wei@example.com—ok

Masked output

联系人张伟,手机<PHONE_1>,邮箱<EMAIL_1>。

Vault

PlaceholderValue
<PHONE_1>13800138000
<EMAIL_1>wei@example.com

5 Two people, two placeholders

Lane rules · 3 × EMAIL

The same address twice gets <EMAIL_1> twice. A second address gets <EMAIL_2>.

Source

Write to ada@example.com or grace@example.com. The desk address is ada@example.com.

Result

#TypeStartEndTextScoreSlice
1 EMAIL924ada@example.com—ok
2 EMAIL2845grace@example.com—ok
3 EMAIL6782ada@example.com—ok

Masked output

Write to <EMAIL_1> or <EMAIL_2>. The desk address is <EMAIL_1>.

Vault

PlaceholderValue
<EMAIL_1>ada@example.com
<EMAIL_2>grace@example.com

6 Text with no PII

Lane rules · no span

These look numeric, and none is a published PII form. A locator that spans them is guessing.

Source

Order 48291 ships as SKU-77219 from warehouse 4. The build finished in 12 minutes on node 3.

Result

No span. Nothing in this text matched a grammar on this lane, and that is the correct answer. A locator that invents a span here would be useless.

Masked output

Order 48291 ships as SKU-77219 from warehouse 4. The build finished in 12 minutes on node 3.

Vault

The vault is empty. A secret never enters it, and this text holds none.

7 Long text, original offsets

Lane rules · 1 × EMAIL

A long document is split into windows internally. The public offset is never a window offset.

Source

Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Email ada@example.com for the desk.

Result

#TypeStartEndTextScoreSlice
1 EMAIL366381ada@example.com—ok

Masked output

Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Note. Email <EMAIL_1> for the desk.

Vault

PlaceholderValue
<EMAIL_1>ada@example.com

8 A log line

Lane rules · 1 × EMAIL, 1 × IP_ADDRESS

An IP address passes an RFC 4291 or RFC 3986 match and then a stdlib parse.

Source

2026-11-04T09:12:33Z level=warn user=ada@example.com src=198.51.100.7 path=/v1/orders action=denied

Result

#TypeStartEndTextScoreSlice
1 EMAIL3252user=ada@example.com—ok
2 IP_ADDRESS5769198.51.100.71.00ok

Masked output

2026-11-04T09:12:33Z level=warn <EMAIL_1> src=<IP_ADDRESS_1> path=/v1/orders action=denied

Vault

PlaceholderValue
<EMAIL_1>user=ada@example.com
<IP_ADDRESS_1>198.51.100.7

9 A prompt before it leaves

Lane en-closed · 1 × EMAIL, 2 × PERSON, 1 × SECRET

This is the product case: keep the sentence, remove the person, prove which characters left.

Source

Summarise this for the on-call engineer: Ada Lovelace reported that ada@example.com cannot reset the password hunter2 from Lisbon.

Result

#TypeStartEndTextScoreSlice
1 PERSON4144Ada1.00ok
2 PERSON4553Lovelace1.00ok
3 EMAIL6883ada@example.com—ok
4 SECRET110117hunter2—ok

Masked output

Summarise this for the on-call engineer: <PERSON_1> <PERSON_2> reported that <EMAIL_1> cannot reset the password <SECRET> from Lisbon.

Vault

PlaceholderValue
<PERSON_1>Ada
<PERSON_2>Lovelace
<EMAIL_1>ada@example.com

10 Two names

Lane en-closed · 4 × PERSON

A name has no grammar and no checksum. Rules own structured forms, models own names.

Source

Ada Lovelace met Grace Hopper at the lab to review the schedule.

Result

#TypeStartEndTextScoreSlice
1 PERSON03Ada1.00ok
2 PERSON412Lovelace1.00ok
3 PERSON1722Grace1.00ok
4 PERSON2329Hopper1.00ok

Masked output

<PERSON_1> <PERSON_2> met <PERSON_3> <PERSON_4> at the lab to review the schedule.

Vault

PlaceholderValue
<PERSON_1>Ada
<PERSON_2>Lovelace
<PERSON_3>Grace
<PERSON_4>Hopper

11 A postal address

Lane en-closed · 2 × ADDRESS, 1 × EMAIL, 2 × PERSON

An address is a model type. The email beside it is a rule type. The locator merges both.

Source

Ship the replacement to Grace Hopper, 12 Rue de Rivoli, Paris. Confirm on grace@example.com before Friday.

Result

#TypeStartEndTextScoreSlice
1 PERSON2429Grace1.00ok
2 PERSON3036Hopper1.00ok
3 ADDRESS385412 Rue de Rivoli1.00ok
4 ADDRESS5661Paris0.87ok
5 EMAIL7491grace@example.com—ok

Masked output

Ship the replacement to <PERSON_1> <PERSON_2>, <ADDRESS_1>, <ADDRESS_2>. Confirm on <EMAIL_1> before Friday.

Vault

PlaceholderValue
<PERSON_1>Grace
<PERSON_2>Hopper
<ADDRESS_1>12 Rue de Rivoli
<ADDRESS_2>Paris
<EMAIL_1>grace@example.com

12 A national id

Lane en-closed · 1 × GOV_ID, 2 × PERSON

V1 ships no national id pattern, by design. This row shows what the model lane buys.

Source

Applicant Ada Lovelace, SSN 121-45-6789, signed the form today.

Result

#TypeStartEndTextScoreSlice
1 PERSON1013Ada1.00ok
2 PERSON1422Lovelace1.00ok
3 GOV_ID2839121-45-67890.90ok

Masked output

Applicant <PERSON_1> <PERSON_2>, SSN <GOV_ID_1>, signed the form today.

Vault

PlaceholderValue
<PERSON_1>Ada
<PERSON_2>Lovelace
<GOV_ID_1>121-45-6789

13 An account handle

Lane en-closed · 1 × EMAIL, 1 × USERNAME

USERNAME is a model type. It is the string that marks an account, not the person.

Source

User lkernan signed in and asked to reset access for lkernan@example.com.

Result

#TypeStartEndTextScoreSlice
1 USERNAME512lkernan0.99ok
2 EMAIL5372lkernan@example.com—ok

Masked output

User <USERNAME_1> signed in and asked to reset access for <EMAIL_1>.

Vault

PlaceholderValue
<USERNAME_1>lkernan
<EMAIL_1>lkernan@example.com

14 A finance note

Lane en-closed · 1 × EMAIL, 1 × PAYMENT, 2 × PERSON

The hardest case in the public score. A finance document does not look like a persona note.

Source

The transfer from Grace Hopper uses card 5490 3479 1287 6543 and routing number 271210785. Receipt to grace@example.com.

Result

#TypeStartEndTextScoreSlice
1 PERSON1823Grace1.00ok
2 PERSON2430Hopper1.00ok
3 PAYMENT41605490 3479 1287 65431.00ok
4 EMAIL102119grace@example.com—ok

Masked output

The transfer from <PERSON_1> <PERSON_2> uses card <PAYMENT_1> and routing number 271210785. Receipt to <EMAIL_1>.

Vault

PlaceholderValue
<PERSON_1>Grace
<PERSON_2>Hopper
<PAYMENT_1>5490 3479 1287 6543
<EMAIL_1>grace@example.com

What these examples do not prove

An example shows that one string works. It does not measure accuracy. A library can pass every string on this page and still score badly on a new domain, and that is exactly what the public score found: the closed encoder's person score falls from 0.995 in domain to 0.048 on finance text.

Use these pages to understand the shape of a result. Use the evaluation guide to decide whether the library is good enough for your text.