<!-- canonical: efficientnewlanguage.org/ai/examples/222-idempotence-witness | ai_layer_version: 0.1.0 | updated: 2026-08-03 -->

# Example 222 — Safe once, not safe twice

`idempotence_witness.eml` applies four cleanup routines up to five times each and checks the property that every retry depends on: `f(f(x)) == f(x)`.

## EML

```eml
# Self-authored for the EML case corpus (no external origin). Operations that
# are safe to run once and not safe to run twice.
#
# A cleanup function is idempotent when applying it again changes nothing:
#
#     f(f(x)) == f(x)     for every x
#
# Almost every "normalize", "sanitize", "trim", "escape" and "migrate" routine
# is written as if this were automatic. It is not automatic - it is a property
# that has to hold, and the ones that fail do so quietly, because the second
# application produces a value that still looks like a clean value.
#
# Four routines are compared, all plausible, all doing the same job:
#
#     strip_prefix     removes ONE leading "-" if present
#     strip_prefixes   removes every leading "-"
#     escape_once      turns "&" into "&amp;"
#     escape_guarded   the same, but leaves an already-escaped "&amp;" alone
#
# `strip_prefix` and `escape_once` are the ones that fail, and they fail in
# opposite directions. Stripping one prefix per call loses data on the second
# call; escaping on every call ADDS data on the second, so "&" becomes
# "&amp;amp;" and a retry that was meant to be harmless corrupts the payload.
#
# Retries are why this matters. A queue that redelivers a message, a form that
# is submitted twice, a migration re-run after a partial failure - all of them
# apply the operation a second time to something that has already had it. The
# system is correct only if the operation is idempotent, and nothing in the
# type of the value records whether it is.
#
# The check is not a spot test. Every routine is applied up to five times to
# every input, and the run is only idempotent if the value stops changing
# after the first application and stays stopped.

def strip_prefix(s):
    # Removes ONE leading dash. Correct once, lossy forever after.
    if len(s) > 0 and s[0] == "-":
        return s[1:]
    return s

def strip_prefixes(s):
    # Removes every leading dash, so there is nothing left to remove.
    0 => i
    while i < len(s) and s[i] == "-":
        i + 1 => i
    return s[i:]

def escape_once(s):
    "" => out
    for ch in s:
        if ch == "&":
            out + "&amp;" => out
        else:
            out + ch => out
    return out

def escape_guarded(s):
    # Skip a "&" that already begins "&amp;". The guard is what makes it a
    # function you can apply twice.
    "" => out
    0 => i
    while i < len(s):
        if s[i] == "&" and s[i:i + 5] == "&amp;":
            out + "&amp;" => out
            i + 5 => i
        elif s[i] == "&":
            out + "&amp;" => out
            i + 1 => i
        else:
            out + s[i] => out
            i + 1 => i
    return out


def apply_n(name, s, n):
    s => v
    for k in [1:n]:
        if name == "strip_prefix":
            strip_prefix(v) => v
        elif name == "strip_prefixes":
            strip_prefixes(v) => v
        elif name == "escape_once":
            escape_once(v) => v
        else:
            escape_guarded(v) => v
    return v

def is_idempotent_on(name, s):
    # f(f(x)) == f(x), and it must stay true for further applications - a
    # routine that settles at the third is still not idempotent.
    apply_n(name, s, 1) => once
    for k in [2:5]:
        if not (apply_n(name, s, k) == once):
            return False
    return True


["--draft", "-x", "plain", "---", "", "a-b", "-"] => dash_inputs
["a&b", "&", "&amp;", "a&amp;b", "plain", "&&", "&amp;&"] => amp_inputs

"input        f(x)            f(f(x))         idempotent"^0
for s in dash_inputs:
    ("%-12s %-15s %-15s %s" % ("'" + s + "'", "'" + apply_n("strip_prefix", s, 1) + "'", "'" + apply_n("strip_prefix", s, 2) + "'", str(is_idempotent_on("strip_prefix", s))))^0

""^0
"the same inputs through strip_prefixes:"^0
for s in dash_inputs:
    ("%-12s %-15s %-15s %s" % ("'" + s + "'", "'" + apply_n("strip_prefixes", s, 1) + "'", "'" + apply_n("strip_prefixes", s, 2) + "'", str(is_idempotent_on("strip_prefixes", s))))^0

""^0
"escaping, where the second application ADDS rather than removes:"^0
for s in amp_inputs:
    ("%-12s %-15s %-15s %s" % ("'" + s + "'", "'" + apply_n("escape_once", s, 1) + "'", "'" + apply_n("escape_once", s, 2) + "'", str(is_idempotent_on("escape_once", s))))^0

""^0
"the same inputs through escape_guarded:"^0
for s in amp_inputs:
    ("%-12s %-15s %-15s %s" % ("'" + s + "'", "'" + apply_n("escape_guarded", s, 1) + "'", "'" + apply_n("escape_guarded", s, 2) + "'", str(is_idempotent_on("escape_guarded", s))))^0

# ------------------------------------------------------------- wider sweep
# Every string of length 0..3 over an alphabet chosen so that both routines
# have something to chew on.
"-&a" => alphabet
[""] => generated
for a in alphabet:
    generated + [a] => generated
for a in alphabet:
    for b in alphabet:
        generated + [a + b] => generated
for a in alphabet:
    for b in alphabet:
        for c in alphabet:
            generated + [a + b + c] => generated

0 => n
0 => sp_ok
0 => sps_ok
0 => eo_ok
0 => eg_ok
[] => sp_witness
[] => eo_witness
for s in generated:
    n + 1 => n
    if is_idempotent_on("strip_prefix", s):
        sp_ok + 1 => sp_ok
    else:
        if len(sp_witness) < 3:
            sp_witness + ["'" + s + "' -> '" + apply_n("strip_prefix", s, 1) + "' -> '" + apply_n("strip_prefix", s, 2) + "'"] => sp_witness
    if is_idempotent_on("strip_prefixes", s):
        sps_ok + 1 => sps_ok
    if is_idempotent_on("escape_once", s):
        eo_ok + 1 => eo_ok
    else:
        if len(eo_witness) < 3:
            eo_witness + ["'" + s + "' -> '" + apply_n("escape_once", s, 1) + "' -> '" + apply_n("escape_once", s, 2) + "'"] => eo_witness
    if is_idempotent_on("escape_guarded", s):
        eg_ok + 1 => eg_ok

""^0
("strings swept:              " + str(n))^0
("  strip_prefix idempotent:  " + str(sp_ok) + "/" + str(n))^0
("  strip_prefixes:           " + str(sps_ok) + "/" + str(n))^0
("  escape_once:              " + str(eo_ok) + "/" + str(n))^0
("  escape_guarded:           " + str(eg_ok) + "/" + str(n))^0

""^0
"where strip_prefix loses data on the retry:"^0
for w in sp_witness:
    ("  " + w)^0
""^0
"where escape_once adds data on the retry:"^0
for w in eo_witness:
    ("  " + w)^0

# --------------------------------------------------- the retry that corrupts
# The scenario, end to end: a message is escaped, delivered, the delivery is
# reported as failed, and the SAME already-escaped payload is retried.
"tom & jerry" => payload
escape_once(payload) => sent
escape_once(sent) => resent
escape_guarded(sent) => resent_guarded

""^0
("original:                " + payload)^0
("escaped once:            " + sent)^0
("retried through once:    " + resent)^0
("retried through guarded: " + resent_guarded)^0

# ------------------------------------------------------------------ checks
0 => passed
0 => checked

checked + 1 => checked
if sps_ok == n and eg_ok == n:
    passed + 1 => passed

# Both broken routines must be visibly broken, or the sweep proves nothing.
checked + 1 => checked
if sp_ok < n and eo_ok < n:
    passed + 1 => passed

# The two failures must be in OPPOSITE directions: one shortens, one grows.
checked + 1 => checked
if len(apply_n("strip_prefix", "--x", 2)) < len(apply_n("strip_prefix", "--x", 1)):
    if len(apply_n("escape_once", "&", 2)) > len(apply_n("escape_once", "&", 1)):
        passed + 1 => passed

# The retry must actually corrupt, and the guard must actually save it.
checked + 1 => checked
if not (resent == sent) and resent_guarded == sent:
    passed + 1 => passed

# A routine that returns its input unchanged is trivially idempotent and
# useless. escape_guarded must still DO something.
checked + 1 => checked
if not (escape_guarded("a&b") == "a&b"):
    passed + 1 => passed

""^0
("checks passed: " + str(passed) + "/" + str(checked))^0
if passed == checked:
    "Two routines settle on the first application; two never do." => verdict
else:
    "FAILED - a routine did not behave as the checks describe." => verdict
verdict^0

""^0
"Nothing in the value records whether it has been through the operation." => n1
n1^0
"That is the whole difficulty: `strip_prefix` cannot tell a string it has" => n2
n2^0
"already trimmed from one that arrived that way, and `escape_once` cannot" => n3
n3^0
"tell an escaped ampersand from a literal one. Idempotence is bought by" => n4
n4^0
"making the OUTPUT recognisable to the function - which is what the guard" => n5
n5^0
"does, and what removing every prefix rather than one does." => n6
n6^0
```

## Python (deterministic transpilation)

```python
def strip_prefix(s):
    if len(s) > 0 and s[0] == "-":
        return s[1:]
    return s

def strip_prefixes(s):
    i = 0
    while i < len(s) and s[i] == "-":
        i = i + 1
    return s[i:]

def escape_once(s):
    out = ""
    for ch in s:
        if ch == "&":
            out = out + "&amp;"
        else:
            out = out + ch
    return out

def escape_guarded(s):
    out = ""
    i = 0
    while i < len(s):
        if s[i] == "&" and s[i:i + 5] == "&amp;":
            out = out + "&amp;"
            i = i + 5
        elif s[i] == "&":
            out = out + "&amp;"
            i = i + 1
        else:
            out = out + s[i]
            i = i + 1
    return out

def apply_n(name, s, n):
    v = s
    for k in range(1, n+1):
        if name == "strip_prefix":
            v = strip_prefix(v)
        elif name == "strip_prefixes":
            v = strip_prefixes(v)
        elif name == "escape_once":
            v = escape_once(v)
        else:
            v = escape_guarded(v)
    return v

def is_idempotent_on(name, s):
    once = apply_n(name, s, 1)
    for k in range(2, 6):
        if not apply_n(name, s, k) == once:
            return False
    return True

dash_inputs = ["--draft", "-x", "plain", "---", "", "a-b", "-"]
amp_inputs = ["a&b", "&", "&amp;", "a&amp;b", "plain", "&&", "&amp;&"]
print("input        f(x)            f(f(x))         idempotent")
for s in dash_inputs:
    print("%-12s %-15s %-15s %s" % ("'" + s + "'", "'" + apply_n("strip_prefix", s, 1) + "'", "'" + apply_n("strip_prefix", s, 2) + "'", str(is_idempotent_on("strip_prefix", s))))
print("")
print("the same inputs through strip_prefixes:")
for s in dash_inputs:
    print("%-12s %-15s %-15s %s" % ("'" + s + "'", "'" + apply_n("strip_prefixes", s, 1) + "'", "'" + apply_n("strip_prefixes", s, 2) + "'", str(is_idempotent_on("strip_prefixes", s))))
print("")
print("escaping, where the second application ADDS rather than removes:")
for s in amp_inputs:
    print("%-12s %-15s %-15s %s" % ("'" + s + "'", "'" + apply_n("escape_once", s, 1) + "'", "'" + apply_n("escape_once", s, 2) + "'", str(is_idempotent_on("escape_once", s))))
print("")
print("the same inputs through escape_guarded:")
for s in amp_inputs:
    print("%-12s %-15s %-15s %s" % ("'" + s + "'", "'" + apply_n("escape_guarded", s, 1) + "'", "'" + apply_n("escape_guarded", s, 2) + "'", str(is_idempotent_on("escape_guarded", s))))
alphabet = "-&a"
generated = [""]
for a in alphabet:
    generated = generated + [a]
for a in alphabet:
    for b in alphabet:
        generated = generated + [a + b]
for a in alphabet:
    for b in alphabet:
        for c in alphabet:
            generated = generated + [a + b + c]
n = 0
sp_ok = 0
sps_ok = 0
eo_ok = 0
eg_ok = 0
sp_witness = []
eo_witness = []
for s in generated:
    n = n + 1
    if is_idempotent_on("strip_prefix", s):
        sp_ok = sp_ok + 1
    elif len(sp_witness) < 3:
        sp_witness = sp_witness + ["'" + s + "' -> '" + apply_n("strip_prefix", s, 1) + "' -> '" + apply_n("strip_prefix", s, 2) + "'"]
    if is_idempotent_on("strip_prefixes", s):
        sps_ok = sps_ok + 1
    if is_idempotent_on("escape_once", s):
        eo_ok = eo_ok + 1
    elif len(eo_witness) < 3:
        eo_witness = eo_witness + ["'" + s + "' -> '" + apply_n("escape_once", s, 1) + "' -> '" + apply_n("escape_once", s, 2) + "'"]
    if is_idempotent_on("escape_guarded", s):
        eg_ok = eg_ok + 1
print("")
print("strings swept:              " + str(n))
print("  strip_prefix idempotent:  " + str(sp_ok) + "/" + str(n))
print("  strip_prefixes:           " + str(sps_ok) + "/" + str(n))
print("  escape_once:              " + str(eo_ok) + "/" + str(n))
print("  escape_guarded:           " + str(eg_ok) + "/" + str(n))
print("")
print("where strip_prefix loses data on the retry:")
for w in sp_witness:
    print("  " + w)
print("")
print("where escape_once adds data on the retry:")
for w in eo_witness:
    print("  " + w)
payload = "tom & jerry"
sent = escape_once(payload)
resent = escape_once(sent)
resent_guarded = escape_guarded(sent)
print("")
print("original:                " + payload)
print("escaped once:            " + sent)
print("retried through once:    " + resent)
print("retried through guarded: " + resent_guarded)
passed = 0
checked = 0
checked = checked + 1
if sps_ok == n and eg_ok == n:
    passed = passed + 1
checked = checked + 1
if sp_ok < n and eo_ok < n:
    passed = passed + 1
checked = checked + 1
if len(apply_n("strip_prefix", "--x", 2)) < len(apply_n("strip_prefix", "--x", 1)):
    if len(apply_n("escape_once", "&", 2)) > len(apply_n("escape_once", "&", 1)):
        passed = passed + 1
checked = checked + 1
if not resent == sent and resent_guarded == sent:
    passed = passed + 1
checked = checked + 1
if not escape_guarded("a&b") == "a&b":
    passed = passed + 1
print("")
print("checks passed: " + str(passed) + "/" + str(checked))
if passed == checked:
    verdict = "Two routines settle on the first application; two never do."
else:
    verdict = "FAILED - a routine did not behave as the checks describe."
print(verdict)
print("")
n1 = "Nothing in the value records whether it has been through the operation."
print(n1)
n2 = "That is the whole difficulty: `strip_prefix` cannot tell a string it has"
print(n2)
n3 = "already trimmed from one that arrived that way, and `escape_once` cannot"
print(n3)
n4 = "tell an escaped ampersand from a literal one. Idempotence is bought by"
print(n4)
n5 = "making the OUTPUT recognisable to the function - which is what the guard"
print(n5)
n6 = "does, and what removing every prefix rather than one does."
print(n6)
```

## stdout (executed)

```text
input        f(x)            f(f(x))         idempotent
'--draft'    '-draft'        'draft'         False
'-x'         'x'             'x'             True
'plain'      'plain'         'plain'         True
'---'        '--'            '-'             False
''           ''              ''              True
'a-b'        'a-b'           'a-b'           True
'-'          ''              ''              True

the same inputs through strip_prefixes:
'--draft'    'draft'         'draft'         True
'-x'         'x'             'x'             True
'plain'      'plain'         'plain'         True
'---'        ''              ''              True
''           ''              ''              True
'a-b'        'a-b'           'a-b'           True
'-'          ''              ''              True

escaping, where the second application ADDS rather than removes:
'a&b'        'a&amp;b'       'a&amp;amp;b'   False
'&'          '&amp;'         '&amp;amp;'     False
'&amp;'      '&amp;amp;'     '&amp;amp;amp;' False
'a&amp;b'    'a&amp;amp;b'   'a&amp;amp;amp;b' False
'plain'      'plain'         'plain'         True
'&&'         '&amp;&amp;'    '&amp;amp;&amp;amp;' False
'&amp;&'     '&amp;amp;&amp;' '&amp;amp;amp;&amp;amp;' False

the same inputs through escape_guarded:
'a&b'        'a&amp;b'       'a&amp;b'       True
'&'          '&amp;'         '&amp;'         True
'&amp;'      '&amp;'         '&amp;'         True
'a&amp;b'    'a&amp;b'       'a&amp;b'       True
'plain'      'plain'         'plain'         True
'&&'         '&amp;&amp;'    '&amp;&amp;'    True
'&amp;&'     '&amp;&amp;'    '&amp;&amp;'    True

strings swept:              40
  strip_prefix idempotent:  36/40
  strip_prefixes:           40/40
  escape_once:              15/40
  escape_guarded:           40/40

where strip_prefix loses data on the retry:
  '--' -> '-' -> ''
  '---' -> '--' -> '-'
  '--&' -> '-&' -> '&'

where escape_once adds data on the retry:
  '&' -> '&amp;' -> '&amp;amp;'
  '-&' -> '-&amp;' -> '-&amp;amp;'
  '&-' -> '&amp;-' -> '&amp;amp;-'

original:                tom & jerry
escaped once:            tom &amp; jerry
retried through once:    tom &amp;amp; jerry
retried through guarded: tom &amp; jerry

checks passed: 5/5
Two routines settle on the first application; two never do.

Nothing in the value records whether it has been through the operation.
That is the whole difficulty: `strip_prefix` cannot tell a string it has
already trimmed from one that arrived that way, and `escape_once` cannot
tell an escaped ampersand from a literal one. Idempotence is bought by
making the OUTPUT recognisable to the function - which is what the guard
does, and what removing every prefix rather than one does.
```

## Round-trip

`ok: true` — round-trip fixpoint reached (python1 == python2)

## Trace event types

eml:run:start · eml:def · eml:assign · eml:output · eml:call · eml:return · eml:run:done
