Commit 3305c92
proof(xml-7-44): make Xml744.Escape.exfiltrate provably total (#79)
## Summary
- Resolves the three `assert_total` proof escapes in
`Xml744.Escape.exfiltrate`'s inner `replaceAll` worker (originally
wrapping partial calls to `strHead`, `head`, and `tail` on Idris2 0.7).
- The earlier refactor that pattern-matched the partial calls away
**left the function failing Idris2's termination check** on 0.8.0 —
recursion through `pack $ drop ...` is not structurally smaller, so the
file did not actually build (`exfiltrate is not total, possibly not
terminating`).
- This PR rewrites the worker as `replaceAllChars : Nat -> List Char ->
List Char -> List Char -> List Char` with a fuel parameter sized to
`length (unpack str)`. Each recursive step consumes ≥ 1 char of the
third argument so the fuel bound is never the binding constraint — it
just makes termination structurally obvious. Matches the Nat-fueled
pattern from the ephapax totality campaign (standards#134).
## Verification
```
$ idris2 -p contrib Xml744/Escape.idr
1/1: Building Xml744.Escape (Xml744/Escape.idr)
Xml744.Escape> :total Xml744.Escape.exfiltrate
Xml744.Escape.exfiltrate is total
Xml744.Escape> :total Xml744.Escape.infiltrate
Xml744.Escape.infiltrate is total
Xml744.Escape> :total Xml744.Escape.infiltrateAttr
Xml744.Escape.infiltrateAttr is total
Xml744.Escape> :total Xml744.Escape.makeSafe
Xml744.Escape.makeSafe is total
```
`grep -E 'assert_total|assert_smaller|believe_me|%unsafe|partial '
src/Xml744/Escape.idr` matches only the new doc-comment line referencing
what is *not* used.
## Out of scope (separate proof debts in this toolkit)
- `Xml744.Attribute` has a pre-existing baseline issue (`decEq` not in
scope for `Bool` on Idris2 0.8.0) and a `PROOF_TODO`-marked `cast
(MkAttrName s)` in `unsafeAttrName` — both predate this branch and are
distinct from the three escapes called out in the proof-debt request.
## Test plan
- [ ] CI green
- [ ] `idris2 --build idris2-ecosystem/xml-toolkit/xml-7-44.ipkg` builds
`Xml744.Escape` cleanly (verified locally; downstream module errors are
unrelated and tracked separately)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 3ed5c3c commit 3305c92
1 file changed
Lines changed: 16 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
51 | 56 | | |
52 | 57 | | |
53 | 58 | | |
| |||
58 | 63 | | |
59 | 64 | | |
60 | 65 | | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
61 | 75 | | |
62 | 76 | | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
| 77 | + | |
| 78 | + | |
73 | 79 | | |
74 | 80 | | |
75 | 81 | | |
| |||
0 commit comments