Trace
Follow a request through every layer
Purpose of this page: show how the parts cooperate. It traces one real
call — a worker claiming a task — from the shell keypress to the SQLite commit,
and names the file responsible at each step.
The call we trace
A worker needs work. Its harness runs:
kanthord node claim <node-id>
Step 1
Commander parses
src/cli/node/claim.ts
the program was built once by
buildProgram in main.ts, with bound handlers
this file holds no business logic and opens no connection itself
▼ options handed to the shared client
Step 2
DaemonClient renders
src/cli/client.ts
takes the operation's typed path tuple from
http/contract/
substitutes :id parameters, builds URL and init (fetch)
attaches the Bearer token of the harness actor
▼ HTTP to the daemon's bind address
Step 3
Middleware chain
src/http/server/
envelope → origin → host → preflight
auth compares the token with
timingSafeEqual
route matches against the operation registry
authorize → bodyParser → idempotency → dispatch
▼ one matched operation, one handler
Step 4
Handler parses
src/http/server/node/
validates the body with the zod schema from the contract
invokes exactly one command:
claimNode
branches on no domain rule — that is a handler defect
▼ the command owns everything below
Step 5
One transaction
src/commands/node/claim-node.ts
storage.transact opens; the clock is read once
expired leases swept · completeness checked on ancestors
lease hierarchy refuses self, parent, sibling conflicts
objective + task leases acquired, fenced
runs opened or adopted · attempt №1 recorded
ready → running, ancestors cascade
lease.claimed and node.running appended
▼ commit, or nothing happened
Step 6
Response formats
handler again
success: lease, fence, run id, attempt id, heartbeat interval (TTL ÷ 3)
refusal: the command threw a typed reason —
lease-held, illegal-transition, … — mapped by the server to an error envelope
▼ same path in reverse
Step 7
CLI prints
worker starts its agent loop
exit code reflects the outcome (
src/cli/exit-code.ts)
on success the worker executes in the clone and heartbeats at the returned interval
What differs on a read
A read such as kanthord node list --state ready follows steps 1–4
and stops: the handler invokes exactly one query, which opens no transaction
and writes nothing. Steps 5–7 belong to write paths only.
Why the shape is rigid
- The CLI cannot bypass HTTP, so the same API serves every client, and the contract stays honest.
- The handler cannot branch on domain rules, so behaviour has exactly one home: a command or query.
- The command owns one transaction, so a transition and its event are all-or-nothing.
- The domain imports nothing impure, so every rule is testable without a database.