docs← Back to article

Markdown for LLMs

Execution rounds: pitfalls

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# Execution rounds: pitfalls

Wrong forms, silent outcomes, `LDC-E` diagnostics, typical mistakes of
formalizers and AI agents, how to detect them. Items marked "confirmed by run"
were reproduced during this research on the installed engine.

## 1. Reading the next round (confirmed by scenario, statics by code)

A round-`r` rule reading a higher-rank round atom (`counter(i + 1)`
in the body with a round-`i` head) is rejected with `LDC-E4120
STAGE_CYCLE_WITHOUT_DESCENT` / `NON_EXECUTABLE_UNSTRATIFIED` — even outside
a cycle and even with a positive cycle shift sum.
Reason: the future round's atom does not exist yet in round `r` — `not_known`
over it is true and not retracted, while a positive read would write into
a finished round. Detection: every read's shift counts from head
to read; a negative shift is a refusal with the rule address, ahead of
producer checks. AI agents often "peek" into
the next round for the minimum/total — a round total is read only from
the next round (a `+ 1` shift on the reader), never the reverse.

## 2. Head without a bound index

A round rule whose index argument is bound by neither a domain literal, nor
a round-predicate read, nor a `+ 1` shift from such a read is
`LDC-E4121 STAGE_UNBOUND_PRODUCER` / `NON_EXECUTABLE_STAGE_PRODUCER`:
a producer without an index has no round
to execute in. Order matters: next-round reads (item 1) check
before producers — a rule reading a future round gets the cycle
refusal, not the producer refusal, even when its index is bound only
by an outside-round read. Detection: every round head must show
one of the three item-2 generation ways.

## 3. Domain, step, grid

An empty domain (`from > to` under `ascending`), a step outside the
`add_calendar_period` calendar units, `to` off the `from + n·step` grid, a
nonexistent grid date (the 31st on a monthly step across February — without
`last_day_of_month`, the declaration is rejected as with `reject_nonexistent`) —
`LDC-E4122` at the compiler, `NON_EXECUTABLE_STAGE` with a reason at the
evaluator. `Integer` has no step; `Date` requires one.
AI agents love "round" boundaries (a quarter-end `to` off-grid) —
the grid counts from `from`, not from the calendar.

## 4. Binds: type, position, overlap

A parameter at a bind position must have the index type — otherwise `LDC-E4123
STAGE_BINDING_TYPE`. One predicate in two `stage`, a second executable
`stage` with overlapping binds, a round rule reading another `stage`'s round
predicate — `LDC-E4124` / `NON_EXECUTABLE_STAGE_MULTIPLE` /
`NON_EXECUTABLE_UNSTRATIFIED`.
Detection: a "predicate → stage" table over all `bind`; an overlap is a
pre-conclusion refusal. Allowed neighbourhood (disjoint) — the
`navier-stokes`/`poincare` specimen (see `corpus-forms.md`, items 5–6).

## 5. Closure and procedure next to stage

Closure over a round predicate (and over an upper rule's conclusion) —
`LDC-E4125 STAGE_CLOSURE_UNSUPPORTED` / `NON_EXECUTABLE_STAGE_CLOSURE`:
a named boundary, not a default. A procedure in a program
with an executable `stage` — `LDC-E4126 STAGE_PROCEDURE_UNSUPPORTED` /
`NON_EXECUTABLE_STAGE_PROCEDURE`: the fold over rounds is undefined.
The bypass specimen — the renovation schedule package: the procedure lives in the
neighbouring package, the bridge is a plan (`corpus-forms.md`, item 3).
Detection by statics; no silent behaviour here, both refusals loud and
pre-conclusion.

## 6. Nonmonotone read with an underived shift

Statics derive a shift only when head and read indices are both domain literals
or the same variable with an item-2 shift; a literal vs another's
variable, two different variables, or another shift-term form give no shift.
A nonmonotone edge (`completion`, `status`, `default`,
`defeasible`, `priority` — everything but `monotone(P)`/`supported(P)`)
without a derived shift is rejected as a next-round read
(`LDC-E4120` / `NON_EXECUTABLE_UNSTRATIFIED`), regardless of cycle:
an instance of such an edge is any rank pair, including a higher-rank
read, and `not_known` over a missing atom is true and not retracted.
A monotone edge with an underived shift is allowed (zero in the cycle sum),
but publishing the head into a finished round at execution is fatal
`STAGE_LATE_WRITE`. The AI-agent trap: an `i == 2`-shaped guard next to a
variable read gives no shift — shifts derive from terms, not guards.

## 7. Empty body — a loud reserve (confirmed by run)

`stage Empty {}` is a legal form (`status: "reserved"`) but
executes in no version: evaluation stops before any conclusion with fatal
`NON_EXECUTABLE_STAGE`, empty `results` and `proofGraph.roots`.
Reproduction during this research (a scratch copy of the teaching package,
installed `law`): `law engine check` — `check OK`, `law test` —
"execution refused: NON_EXECUTABLE_STAGE". The reverse would be the mistake:
keeping a reserve in a live package "for the future" and waiting for a
conclusion. A text finding: the binary message says "introduced only in 0.3"
— stale wording (rounds run under the current `0.2` revision), the refusal itself holds.

## 8. Silent outcomes that read as mistakes (but are not)

- An empty round is not a refusal: a round with not one application counts
  towards `maxStages`, execution runs to `to`: domain `1…3` with `maxStages = 2` gives
  `RESOURCE_LIMIT`, not a round skip.
- `NEITHER` on a missing start is the norm: an unstarted counter stays silent
  (the no-seed scenario test), while the document stays complete.
- An application with a rank above current is not published now and is
  reconsidered in its own round — neither loss nor double.
- An explicit tail of the former revision in the query (`0.2.0`…`0.2.3`) with an
  executable body gives the former `NON_EXECUTABLE_STAGE`:
  fixed not by editing the body but by the family name (`0.2`) or the `0.2.4`
  revision.