.tmc can declare a fair amount about a program — alphabets and tape typing, routine and graph signatures, writes/preserves contracts with footprint inference, volatile tapes, [deprecated], and, once the binding arc lands (#95, #118), state parameters as exits, noreturn, named maps and alphabet import. The question this issue asks is the one #95 deliberately did not: is that everything a library author and a large program need, or are there facts about a routine that the language can only state in prose? Like #95 this is an analysis, not a fix — verdicts per line, and a sketch for anything judged worth adding.
The starting evidence is again the standard library's own header, which says of its doc lines: "The ? lines on each entity are its normative contract, including where the head sits on entry and on exit." A normative contract that lives only in prose is the thing to look at first.
Lines of inquiry
1. Head position is part of every stdlib contract and is machine-invisible.
Every std routine documents where the head must be on entry and where it rests on exit ("On entry the head is on the number (any cell up to and including its '$'); on exit it rests on that '$'"). Nothing checks it: not the compiler, not a lint, and not the testing library #30 will become, because the fact has no representation. This is the failure mode of real library use — calling plusOne with the head one cell off — and the footprint engine already walks bodies for writes. Determine what a head clause would have to say to be checkable (entry precondition as a glyph set the head must be on; exit postcondition as a glyph set, or same/moved relative to entry; per tape), whether inference can confirm it the way it confirms writes (the same over-approximation caveat for substitution writes applies), and whether it belongs in the interface section and headers so a caller's footprint can use it.
2. A routine generic over its alphabet.
goToEnd-shaped behaviour depends on the blank and nothing else, yet a routine is typed by one concrete alphabet and reuse over another goes through a map. Index binding already gives de-facto duck typing, but there is no way to declare "this routine needs only the blank and these two symbols; anything else is opaque and passed through". Determine whether an alphabet parameter on a signature (routine r<A>(tape t: A) with a required-glyph constraint) is expressible on top of the composition engine — the callee's rows would be written against required symbols plus a wildcard for the rest — or whether index binding plus the item-4 warning from #95 is the honest limit.
3. Named glyph sets.
'0'..'9' is respelled in every pattern that needs it, in the stdlib and in rpnhex.tmc. A declaration (set digits = { '0'..'9' }) usable in pattern cells, write vectors and contract clauses would name the semantics once. Small; decide whether it earns its keyword, and how it interacts with ranges, as bindings and folds.
4. Trap behaviour as part of the interface.
noreturn states that a routine never executes ret; nothing states whether it can leave by a trap (UnmappedRead/UnmappedWrite/NoTransition). Today that is the compile-time lint state-may-trap, which a library consumer never sees. Determine whether "never traps" (or the set of traps a routine may raise) is a fact worth carrying as a clause and in the interface section, and whether the existing analysis behind state-may-trap can back it.
5. Representations.
"A number in the bare representation" is a convention described in a namespace comment; named maps and alphabet import (from #95) give half of it, the alphabet. The other half — the shape invariant of the tape — may belong to the testing library rather than to types. Settle which, so the question stops recurring.
Method
Not by argument. Three probe programs, each written against the current language plus the #95 design, each either written without friction or stopping at the missing word:
- a library over two representations whose head preconditions are checked rather than documented (line 1);
- one routine generic over its alphabet, used over three different alphabets (line 2);
- decimal arithmetic over a rich alphabet, where named sets are either needed or provably not (line 3).
The probes live under docs/superpowers/ while the analysis runs; whatever survives becomes an example or a stdlib routine.
What a good outcome looks like
A written verdict per line — inherent / worth adding / not worth adding — with the probe that decided it, and for anything judged worth adding, enough of a sketch to become its own issue. Line 1 is the one that changes what a contract is; lines 2–5 mostly need settling.
Docs that bound the current language: docs/tmt/language.md (contract clauses, substitution), docs/tmt/stdlib.md, the ? lines throughout crates/turing-machine/src/stdlib/std.tmc, and the binding-arc spec docs/superpowers/specs/2026-09-13-issue-95-binding-analysis.md for what the language will already have.
.tmccan declare a fair amount about a program — alphabets and tape typing, routine and graph signatures,writes/preservescontracts with footprint inference, volatile tapes,[deprecated], and, once the binding arc lands (#95, #118),stateparameters as exits,noreturn, named maps and alphabet import. The question this issue asks is the one #95 deliberately did not: is that everything a library author and a large program need, or are there facts about a routine that the language can only state in prose? Like #95 this is an analysis, not a fix — verdicts per line, and a sketch for anything judged worth adding.The starting evidence is again the standard library's own header, which says of its doc lines: "The
?lines on each entity are its normative contract, including where the head sits on entry and on exit." A normative contract that lives only in prose is the thing to look at first.Lines of inquiry
1. Head position is part of every stdlib contract and is machine-invisible.
Every
stdroutine documents where the head must be on entry and where it rests on exit ("On entry the head is on the number (any cell up to and including its '$'); on exit it rests on that '$'"). Nothing checks it: not the compiler, not a lint, and not the testing library #30 will become, because the fact has no representation. This is the failure mode of real library use — callingplusOnewith the head one cell off — and the footprint engine already walks bodies forwrites. Determine what a head clause would have to say to be checkable (entry precondition as a glyph set the head must be on; exit postcondition as a glyph set, orsame/movedrelative to entry; per tape), whether inference can confirm it the way it confirmswrites(the same over-approximation caveat for substitution writes applies), and whether it belongs in the interface section and headers so a caller's footprint can use it.2. A routine generic over its alphabet.
goToEnd-shaped behaviour depends on the blank and nothing else, yet a routine is typed by one concrete alphabet and reuse over another goes through a map. Index binding already gives de-facto duck typing, but there is no way to declare "this routine needs only the blank and these two symbols; anything else is opaque and passed through". Determine whether an alphabet parameter on a signature (routine r<A>(tape t: A)with a required-glyph constraint) is expressible on top of the composition engine — the callee's rows would be written against required symbols plus a wildcard for the rest — or whether index binding plus the item-4 warning from #95 is the honest limit.3. Named glyph sets.
'0'..'9'is respelled in every pattern that needs it, in the stdlib and inrpnhex.tmc. A declaration (set digits = { '0'..'9' }) usable in pattern cells, write vectors and contract clauses would name the semantics once. Small; decide whether it earns its keyword, and how it interacts with ranges,asbindings and folds.4. Trap behaviour as part of the interface.
noreturnstates that a routine never executesret; nothing states whether it can leave by a trap (UnmappedRead/UnmappedWrite/NoTransition). Today that is the compile-time lintstate-may-trap, which a library consumer never sees. Determine whether "never traps" (or the set of traps a routine may raise) is a fact worth carrying as a clause and in the interface section, and whether the existing analysis behindstate-may-trapcan back it.5. Representations.
"A number in the bare representation" is a convention described in a namespace comment; named maps and alphabet import (from #95) give half of it, the alphabet. The other half — the shape invariant of the tape — may belong to the testing library rather than to types. Settle which, so the question stops recurring.
Method
Not by argument. Three probe programs, each written against the current language plus the #95 design, each either written without friction or stopping at the missing word:
The probes live under
docs/superpowers/while the analysis runs; whatever survives becomes an example or a stdlib routine.What a good outcome looks like
A written verdict per line — inherent / worth adding / not worth adding — with the probe that decided it, and for anything judged worth adding, enough of a sketch to become its own issue. Line 1 is the one that changes what a contract is; lines 2–5 mostly need settling.
Docs that bound the current language:
docs/tmt/language.md(contract clauses, substitution),docs/tmt/stdlib.md, the?lines throughoutcrates/turing-machine/src/stdlib/std.tmc, and the binding-arc specdocs/superpowers/specs/2026-09-13-issue-95-binding-analysis.mdfor what the language will already have.