ADR-236: A batch over a folder is a draft per record
- Status
-
Accepted
- Date
-
2026-11-01
- Amends
-
ADR-162 (a second bound, for a batch that does not run in the request)
- Authors
-
Netresearch DTT GmbH
Context
ADR-162 runs a bulk editor action as N ordinary runs inside one backend request and stops at 20 records, because a request can time out. It named the way past the cap: move the loop onto the queue, a separate decision. ADR-234 made a queue that does not run in the caller, and ADR-235 made the alternative text come from the image. What is left is the scope: a folder of two hundred images, a section of a site, and a scheduler that goes through them without anybody opening a page.
The guided tours of this project hold to the rule that nothing is saved without confirmation. A scheduled batch has nobody present, so it has to say where it stands on that rule.
Decision
A batch is still N ordinary runs. Everything ADR-162 derives from that holds:
N turns, N digests, N verdicts, one catalogue call per record. Only the loop
moves, from run to defer.
It is a draft, per record. A batch writes nothing. Each run ends at its tool call, which suspends for approval (ADR-134), so the generated text stands on an approval card and the field keeps its value until somebody approves that card. That is the rule of the tours, kept: nothing is saved without confirmation. There is no direct-write switch. A declared write is approved whatever the configuration says (ADR-202), and a batch verdict is what ADR-133 refuses, so a switch would have to reverse both for a surface that writes to many records at once.
Whose rights. A writing tool acts for a person and refuses a service account.
The page queues under the editor's own frozen actor, as every background run does
(ADR-234). nrllm: needs --, an
active backend user whose rights the runs have and who finds the cards in their
inbox. It is never _cli_, whose admin flag says nothing about who asked. A
user disabled after the batch was queued yields no acting user, and the run fails.
The catalogue asks whether the actor may use the default configuration through
Configuration, not through the ambient user: on the
command line that would be _cli_, and everyone would pass.
The image is read in the worker. A queued request names its file in
image. Scaling two hundred images inside a request is the timeout this
record leaves behind, and two hundred data URIs in the run table are a queue full
of copies. The worker reads the image as the acting user, through the same gate
(ADR-235), so a file that moved or a right that went away is
decided when the run starts. A run whose image cannot be sent fails, because no
model should describe an image it does not have.
A repeated batch is harmless. The origin of a run is
batch:<tool>:<table>:<uid>, per record. A record is skipped when it has a run
that is open or ended in a decision: approved, rejected, or declined by the model.
A person who said no must not get the same card on every schedule, and an image
approved as decorative holds an empty text on purpose. A run that failed, was
cancelled, ran out of budget or was cut short says nothing about the record, so
the record is tried again. A decision lasts as long as its run is kept.
A record is also skipped when it holds a value in any field a vision action fills:
the prompt asks for all of them, so a file with one written would get a proposal to
replace it. A file with a description and no title therefore stays as it is. A
field switched off is not counted. A daily schedule picks up what arrived since,
and a batch never overwrites a text. The -- option adds a column to
that check. A decision covers the record for that action: a second batch of the
same action with another -- column skips what the first one decided.
A queued run on a page reads the page. A run has only the writing tool it was started for, so the prompt carries the text of the page and its content elements, read when the batch is queued. A vision run has its image instead.
A second bound. Editor is 100
open runs of one action. It is not about timeouts. It bounds the cards an action
hands an approver, the second constraint ADR-162 named, and it is the number of
cards the inbox shows, oldest first. Open runs count, so a daily schedule does not
stack cards faster than somebody decides them. What the scope holds beyond it is
reported and picked up by the next batch. A record the catalogue refuses takes no
place, or a folder that starts with documents would never reach its images.
Consequences
- A folder of 100 images is 100 cards, each decided on its own. That is the price of ADR-133, and it is the reason the bound exists. With a full inbox a later card of another action stays out of view until older ones are decided. An installation that wants this to be less work needs a different approval unit, which is its own decision.
- A scheduled batch needs a user who reads an inbox, and something that works the
queue:
nrllm:or a consumer.agent: work - A run in the queue carries a request, not an image. A run waiting for approval
does carry it, in
suspended_, until it settles (ADR-235).state - The cost estimate of the batch page does not count the image, as for the synchronous page.
- The budget stops a batch per user in the sweep, and the runs stay queued (ADR-234).
- A page tree is read with the acting user's page permissions. A folder is listed with the rights of the process and filtered per file as the acting user.
Alternatives considered
Direct write behind an explicit opt-in. It would make a scheduled run finish a folder unattended, and it is what a large archive would want. It needs a write path outside the tool loop, since a tool write always suspends, and it would save generated text under an editor's name without that editor seeing it. Left to a decision of its own, with an approval unit to match.
A proposal table holding the generated texts. A list an editor works through in one view is a better surface for 100 texts than 100 cards. It is a second place that holds a pending write, with its own lifecycle, next to the suspended run that already does.
Revisit when
- Measured use shows approvers giving up on the cards.
- ADR-133 is reopened for a verdict over several runs.