@network-harness/protocol-joint-search
v0.2.0
Published
Part of the network harness: @network-harness/protocol-joint-search.
Readme
@network-harness/protocol-joint-search
Two humans have a question neither one's data can answer alone, and neither will hand their data to the other.
This is the protocol the rest of the harness exists for, and it negotiates twice.
First over what to compute. Each side sees only the other's descriptor -- source names and a sentence each, never contents -- and the two agents write objectives into a shared versioned resource: one suggests, the other reads the diff and suggests back, until one agrees. An objective names, per node, exactly which sources it may read, what the terms in it mean, the rules a program must follow, and what may and may not come out.
Then over how. The same machinery produces program.py -- real Python
defining run(parties), which is what the box's runner executes -- and both
sides approve those exact bytes. The instructions carry the box's own execution
contract: the party order, the shape each party's input arrives in, the modules
that may be imported, the bounds, and the rule that nothing may depend on the
clock or randomness. Only then does anything private move, and it moves into a
box both sides verified, carrying exactly the sources the agreed objective
named.
Everything hard here belongs to a component: the versioned resource and its
bundles are the artifact store's, the runs and their output contract the loop's,
the sessions and delivery the adapter's, and every step that touches material is
an apply. What is left is the state machine -- who initiates, what each side
owes next, and when a negotiation has gone on long enough.
| | |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| routes | POST /queries, GET /queries, GET /tasks, GET /works, GET /descriptor |
| payloads | probe.* (triage), plan.* (objectives), program.*, work.* (the box) |
| schedules | publish 30s, triage 5s, pair 5s, advance 2s, sweep 30s |
| needs | any source -- which ones is the negotiation's own answer, and policy decides what may actually be applied -- the jc.* operations, with jc.submit gated |
| intents | search, declared fallback: publishing a query needs nobody to have offered anything first |
Roles are elected from the two node ids, so both sides derive the same
initiator without being told. descriptor.ts is what a peer may learn,
prompts.ts what each run is asked (and the box contract), state.ts the
durable records.
Running it live needs a real box, because the in-process double cannot join two
processes: see devtools/README.md. The scripted
path is services/daemon/tests/joint-search.spec.ts, which is also the
reference for what a negotiation script looks like.
