@projectpac/jc-box-run
v0.6.0
Published
Part of PAC: @projectpac/jc-box-run.
Readme
@projectpac/jc-box-run
What two principals agreed, carried out in a box neither of them owns: the session's state machine -- party, propose, view, approve, submit, fetch -- advanced one durable step at a time, so a restart resumes where the records say it was rather than where a variable hoped it was.
A factory rather than an actor. A flow hands over a spec -- its record accessors, its choices, its messages -- and drives what comes back with its own hands: every box call goes through a closure over the flow's own context, so attribution, policy, and inject gates are exactly what they were when the flows inlined these steps.
const run = ctx.jcBoxRun.drive<Work>({
noun: "work",
runner: "python",
box: () => ctx.jcBox,
network: () => ctx.network,
messages: {
party: "work.party",
session: "work.session",
failed: "work.failed",
},
// the record accessors, the program, the party, what this side stakes
});
await run.advance(id);Why it is not part of the box adapter
@projectpac/operation-jc-box is a request-in, response-out seam to one
external system, and it is the thing a principal's policy gates. This speaks to
peers, owns payload types, and holds a record's state machine across restarts.
Keeping them apart is also what lets a flow build its drive at load on a node
with no box installed: skills serves its board that way and fails a call, rather
than the whole flow waiting for an adapter it may never get.
Why it is not part of the negotiation engine
@projectpac/negotiation agrees bytes and knows nothing about what the bytes
are for. This drives one particular mechanism for carrying them out. A flow
pairs them when it wants to, and meta does not: it agrees a package with rounds
and carries it out by installing it on both nodes.
The wire
The three landmarks each side tells the other -- a party key, the session,
giving up -- are the same in every flow that rides the box. Name their payload
types in messages and the engine sends them at the landmarks and reads them in
handle, applying the same-session rule; a flow whose messages have a shape of
their own keeps onParty and onSession instead. Every message names its
record by the id key answers to, so one drive serves however many records a
flow runs.
boxStateFields is spread into the flow's own record schema: the record stays
the flow's, and the engine still has somewhere to write the party keys, the
session, and the program hash.
