# "`complete` takes an event hash, not a boolean"

> worklists.dev — 2026-08-20
> Written for ED-1 — the supply-chain ISV / traceability-vendor engineering org — the vendor engineer whose customer asked for task completion that cannot be faked, and who has been shipping a checkbox.

One thesis: **`complete` takes an event hash, not a boolean, and that one decision in the type
signature is the difference between a system that records a button was pressed and a system that
records work was done.** Everything else on this door is support for it.

## The boolean is the problem

Every task system you have integrated with closes a task the same way: somebody taps Done, and a
`completed: true` lands in a row with a timestamp. The system is honest about what it knows. It
knows that at 06:14 a session with a given login produced a tap. It does not know who was holding
the device, where the device was, or whether the bag of lettuce that task was about was anywhere
near it.

Then a chargeback arrives for a short shipment, or an auditor asks for the receiving record on a lot
under a recall, and the boolean is produced as evidence. It is not accepted, and it should not be.
A boolean is a claim by the application. Nobody outside the application can check it.

## What the signature does instead

```ts
complete(record, {
  taskId, tenant,
  artifact: { kind: "event-hash", digest },
  by, at, actionId, seq, ns,
});
```

The closing argument is the hash of an EPCIS event that already exists on the spine — a CBV §8.9
event hash from [epcis.dev](https://epcis.dev). That event was captured through an attestation of
the performer's identity, at a read point, at a time. So what the task record holds at settle is a
pointer to **a real *who*, at a real place, inside the window**. The record of work done is the
same object as the evidence it happened.

The package refuses eight shapes of settlement with a typed problem, among them `true`, a bare
string, a pack digest, a 63-hex digest, and a second settle on a closed task. The one that actually
occurs in practice is the **empty digest**. A settle path that has nothing to hash yet reaches for
`""` rather than for the error, and a system that accepted it would be back to a boolean with extra
steps. It is refused.

## A receiving count, end to end

A PO for forty cases of lettuce arrives at [transactions.dev](https://transactions.dev). `dispatch`
converts it into a receiving task at dock 12 with a window. On Monday morning a receiver points a
scanner at the SSCC on the pallet. The [barcode layer](https://barcoding.dev) decodes the mark and
names the step; the identity rail attests who is holding the device; the event lands on the spine
and comes back with a hash.

`complete(task, hash)` fires. The task folds to `settled`. Ask `trace` about it later and you get
the PO that dispatched it, the receiver's attested identity, dock 12, 06:14, and the event hash —
and the event itself is one more hop away on the spine, where it was always going to be, whether or
not any task had existed.

Notice what the receiver did: one scan. No tap, no confirm dialog, no form. The close path requires
no reading because the confirm *is* the scan.

## What it refuses to do, and why

**It does not write to the spine.** There is one public write door in this family, and it is
`epcis.dev.capture`. `complete` returns a `captureIntent`; it never performs the capture. The
package's surface test greps its own source for `fetch`, `XMLHttpRequest`, `node:http` and
`WebSocket` and fails on a hit. A work door that could write events would be a second source of
evidence, and two sources is how evidence stops being evidence.

**There is no `reopen`.** A completed task is closed. If the wrong event closed it, the correction
happens at the event grain: `epcis.dev.correct` emits a new event carrying an `errorDeclaration`,
and the task's history shows the original settle and the correction beside it. A `reopen` verb would
make the task record editable and break the append-only law one layer up.

**It never returns a score.** The settle carries the hash and its attestation grade. It does not
carry a duration, a count against a target, or anything that could be summed across people. That
is a boundary on the door, not a rendering choice.

## For the vendor

If your product already emits EPCIS events, you are most of the way there. The work is to stop
treating task completion as a field your UI sets and start treating it as a pointer your UI
obtains. The hash exists the instant the capture is acknowledged; `complete` is one call with it.

Your customer asked for task completion that cannot be faked. It falls out of the spine rather than
being built on top of it. Get started with the package and settle one task with one real hash, and
then try to settle it with `true`. The refusal is the demonstration.

---
Get started: https://worklists.dev/get-access/ · All posts: https://worklists.dev/blog/ · Machine face: https://worklists.dev/llms.txt
