Skip to content

Latest commit

 

History

History
337 lines (291 loc) · 21.9 KB

free-labor.md

File metadata and controls

337 lines (291 loc) · 21.9 KB

Recoverable coding orders

crates/coder-labor implements one bounded buyer/provider coding order over NIP-MKT and NIP-LAB. It is a Rust library host with a reproducible local acceptance fixture. The default remains free. An explicitly admitted fixed postacceptance Lightning profile additionally joins current canonical partner custody, protected execution and checking, signed acceptance, and authenticated inbound funding to the existing central ledger. Independent commercial operation remains unqualified.

The retained acceptance evidence contains the original signed and encrypted events, both role journals, both process traces, artifact manifests, and candidate bytes. The source and all identities in that fixture are synthetic. The implementation was written in this public repository; it contains no copied private service implementation.

Authority and state

The host preserves four separate decisions:

  1. Buyer and provider confirm the exact commercial order. The free profile has a zero price and fee limit. Confirmation creates no process authority.
  2. The buyer binds a signed CJ request to that order. The provider's operator separately supplies a local task execution grant. Both must agree before the existing task owner can dispatch a process.
  3. The provider submits exact deliverable artifacts and an attributable RUN chain. The buyer records availability and runs its own admitted checker. A successful process or checker does not accept the order.
  4. The buyer signs its review and final acceptance. Acceptance changes no balance and invokes no wallet. A disputed order remains unresolved because this first host does not execute a resolver.
flowchart TD
    A[Operator pins contracts and source] --> B[Encrypted RFQ and quote]
    B --> C[Buyer order and provider confirmation]
    C --> D[Buyer binds original signed CJ request]
    D --> E[Separate local operator execution grant]
    E --> F[Persist dispatch intent]
    F --> G[Durable bounded task owner]
    G --> H[Retained candidate and process trace]
    H --> I[Provider submission and buyer delivery receipt]
    I --> J[Separately authorized buyer checker]
    J --> K[Buyer review]
    K --> L[Buyer acceptance or unresolved dispute]
Loading

A CJ request with requires: ["openagents.labor-binding.v1"] is accepted only through the explicit labor decoder. Generic workers still refuse it. The host checks the original signature and body fingerprint; it does not strip the feature or rewrite the signed request to make a generic worker execute it.

Supported contract

admission::Admission is an operator-selected closure of exact artifacts. The receiver cannot choose the host's source, target, checker, rights, or recipient by sending a different relay declaration. Admission checks the pinned artifacts and the following supported subset:

Component Supported behavior
Parties One buyer and one provider that is also the worker; all-in-one ownership is disclosed in the fixture.
Price Free by default. The optional paid setup pins exact positive BTC millisatoshis, zero added platform fee, one buyer-approved selection, and a fee ceiling. It provides no escrow.
Definitions Exact target and checker CAP definitions with complete single-component locks.
Source One retained repository source in an original buyer-owned task frame; an exact commit and workspace snapshot bind the task input.
Instructions A pinned empty instruction set under coder.free-labor.empty-instructions.v1; arbitrary instruction resolution refuses.
Disclosure coder.free-labor.disclosure.v1 admits the named buyer and worker under the explicit trusted-command profile. No implicit external model or fallback recipient is admitted.
Execution Exact local program bytes, argument digest, write mode, wall time, stream cap, memory cap, source snapshot, task identity, and intent digest must match the operator grant.
Resources CJ bounds cover one job, elapsed time, and retained process output. The output ceiling includes the owner's 2 MiB streamed stdout allowance plus both captured stream caps. Deliverable size has its own bound. This is not a whole-filesystem disk quota.
Deliverables Complete named set, exact artifact bytes, declared schemas, and maximum sizes.
Checks Pinned checker and lock, exact submission/input/criteria, attributable checker receipt, and separate buyer verification.
Rework Zero executable reworks. Requests are retained as refusals; they cannot expand the existing grant or move its deadline.
Disputes Buyer/provider declarations are retained with their causes and evidence. Direct final acceptance then refuses; resolver execution is unsupported.
Rights Exact license, recipient, use, publication, training, evaluation, redistribution, and retention declarations are pinned. The fixture exercises restrictive rights with synthetic material.
Recovery Exact duplicate events replay as duplicates. Missing or conflicting state never grants permission to replace a dispatch.

The local command is explicitly trusted by its operator. The task owner supplies workspace-and-system read scope, filesystem write confinement, and subprocess bounds. Network behavior follows the actual platform boundary in the task receipt; on macOS the current owner denies external IP access while allowing localhost. These are explicit limits, not an arbitrary disclosure-policy engine. This lane must not be advertised as an arbitrary untrusted remote-code execution service or as enforcement of every possible disclosure policy.

Signatures attribute a declaration to a key. A signed provider RUN chain or buyer checker receipt is not remote hardware attestation. The acceptance fixture additionally runs the real provider and buyer processes locally and retains their task-owner evidence.

Host API and persistence

A caller constructs book::Setup from its admitted offering, encrypted terms, market identity, and closure. store::Store::open receives the endpoint key in memory; no secret key is serialized into its journal. Its API is:

  • receive(event, observed_time, attachments): verify the private event, apply the supported transition, and retain the event, exact attachments, local observation time, and outcome before returning.
  • dispatch(event, grant_bytes, task_directory, observed_time): check the confirmed order and original linkage, persist dispatch intent, submit the immutable task, and invoke coder::task::owner::execute under the separate grant.
  • execution::prepare_frozen: validate an already admitted CJ attempt's exact command bytes, requirements, local task ID, and separate operator grant. A native repair host can assign each attempt a distinct local task while preserving the commercial order's CJ request and run; this helper neither admits an order nor dispatches it.
  • reconcile(): recover that same task identity. A missing or not-started task remains unknown; a different frozen intent refuses. It never starts another attempt.
  • observations(): read the retained applied, duplicate, gap, conflict, and refusal observations.

The private directory is created as 0700; ordinary journal and lock files are 0600. The store holds an OS lock, checks its stable inode before mutation, rejects symlinks and hardlinks, atomically replaces a synced journal, and syncs the directory. An initialized directory missing its journal or lock refuses instead of starting a new history. An uncertain write poisons the open handle until recovery. The closure is bounded to 256 artifacts and 8 MiB; the journal is bounded to 256 observations and 16 MiB.

transport::publish and transport::fetch open bounded WebSocket connections, require NIP-42 authentication acknowledgment, and verify exact event identity, signature, and private recipient access. Reconnect fetches the retained event; missing evidence is unavailable. Each operation has a ten-second deadline, a message bound, and a 1 MiB message limit. Relay selection and endpoint-key admission remain the calling host's responsibility. There is no discovery service, background subscription daemon, or deployment in this slice.

Explicit paid fulfillment

book::Setup.paid selects the fixed postacceptance Lightning lane. It pins the canonical accepted partner assignment and its separately priced BTC obligation triggered by accepted delivery, source and disclosure closure, trusted policy issuer and current epoch, provider and central receive destinations, and independent buyer checker. Its exact scope allows one bounded UTF-8 patch file and zero executable revisions or reworks. A request for additional work retains its signed cause and support action; a new accepted order is required to execute it.

dispatch_paid reads the current signed policy and authenticated canonical pipeline before dispatch and while the existing task owner runs. Canonical custody locks are released between checks so permission can be revoked. A signed cancellation, rework request, or unavailable current admission stops unaccepted execution. The existing task identity and failed or unknown result remain retained. Policy, credentials, labor journals, checker custody, wallet state, and the central ledger must stay outside provider workspace writes.

verify_paid_delivery runs the separately admitted /usr/bin/cmp checker under the same bounded task owner. Before earning can accrue, the host joins the exact provider patch to retained task artifacts and RUN dispatch evidence, and joins the signed LAB verification to the actual protected checker result. Passing a checker does not supply buyer acceptance. Later cancellation does not erase an already accepted obligation.

openagents labor execute requires --pipeline, --credential, and --authority-evidence for a paid book. labor verify uses those same explicit private sources. labor support receives one signed private support, cost, rework, or cancellation event; it queues narrowing notices for a running book. labor invoice additionally requires an explicit resident --wallet-home and prepares one exact invoice after acceptance. The buyer separately authorizes payment through openagents x402 node pay BOLT11 --max-fee-msat N, where N is the exact accepted fee ceiling. The payer must check the retained invoice, amount, central destination, and payment deadline before authorizing it. labor fund --ledger FILE verifies the resident node's exact inbound lookup before calling record_worker_earned. It opens no replacement node and performs no outgoing payment or payout. It verifies the retained signed invoice separately from optional lookup invoice metadata and leaves absent fee evidence unknown. Invoice creation and funding lookup carry the admitted node identity to the resident, which refuses a replaced node before either operation. It rechecks the admitted payout destination after the lookup before accrual. Invoice preparation reserves the resident's 60-second reply bound and one second of timestamp rounding within the original payment deadline. It refuses an insufficient window before issuance, then refreshes the observed clock and current admission after creation. The returned and retained invoice shows its actual shorter expiry; the signed payment deadline stays fixed.

Interrupted invoice preparation remains unknown and cannot silently issue a replacement. Unknown funding creates no liability; failed or conflicting funding refuses credit. Exact retries, restarts, and relay replacement preserve the obligation and payment identities. The existing central ledger retains the worker payable share and owns later payout reservation and reconciliation.

The private paid report retains attributable support and signed cost evidence for coordination, execution, checking, failed attempts, and payment fees. Missing categories stay unknown, and no complete all-in cost or commercial qualification is inferred. BTC fulfillment remains explicitly denominated; USD service contribution remains unknown until separately compatible cost evidence exists. Real independence, source rights, customer demand, wallet funding, and payout qualification remain in NEEDS_OWNER.md.

Reproduce the acceptance fixture

Use the repository's pinned toolchain and a worktree-specific target directory. The fixture invokes local /usr/bin/git, /bin/sh, and /usr/bin/cmp through the task owner, so it requires a supported macOS or Linux execution boundary. It uses no model account, paid API, real wallet, public relay, or private repository. The paid test uses a signed fake BOLT11 and authenticated fake receive lookup; it exercises actual local execution and central liability with synthetic source and operators.

Run cargo test --locked -p coder-labor --lib -- --test-threads=1 with your existing CARGO_TARGET_DIR. To include the paid CLI process fixture, first build openagents-cli --bin openagents with the same target directory, then set CODER_LABOR_CLI to that binary's absolute path for the library test.

To retain a fresh successful process and relay fixture rather than deleting its temporary working directories:

Set CODER_LABOR_ACCEPTANCE_DIR to a directory below openagents scratch, then run the same library test. It prints the retained fixture directories.

The test generates a synthetic Rust file returning 41, freezes expected bytes returning 42 before dispatch, and grants one exact shell edit. The buyer copies the retained candidate as data into a separate checker workspace and grants a read-only cmp against those frozen bytes. It publishes and retrieves signed private agreement, linkage, submission, availability, verification, review, and acceptance records over fresh authenticated connections. Both role journals reconstruct acceptance after relay shutdown.

One retained free-order run observed 47 ms for the provider process and 60 ms for the buyer checker. Those are single process observations, not a speed benchmark or full transaction latency. There were zero inference calls. The commercial price is zero; total CPU, storage, energy, and operator costs are unmetered, so all_in_cost_usd is null.

The paid fixture negotiates a synthetic 10,000 msat price. Its optional CLI process check reopens already verified journals, reconciles authenticated fake funding twice, refuses unauthorized or canceled execution, and checks the retained funding state. Fresh provider and protected checker execution run through the owning Rust API in the same fixture. These checks do not establish an independently operated paid service or real collection.

The suite also tests missing closure, changed pins and bytes, unauthorized readers, invalid signatures, wrong publishers, duplicates, restart, late delivery, failed or unknown checks, unknown execution, zero-rework refusal, unresolved disputes, missing journals or locks, replaced lock inodes, and closure overflow without mutation. The unknown-dispatch check injects the persisted intent-before-submit state; it is explicitly a recovery fixture, not a claimed operating-system crash experiment.

Delivery roles after execution

crates/labor-roles carries an order from submission to its final record with every role a separate participant: a worker, a reviewer, a buyer and a resolver, each a host::Host with its own key, 0700 directory and journal, exchanging signed private 3188 records sealed to the other roles. The terms admit only distinct role keys with declared operators where the buyer, the provider side, a non-buyer reviewer and the resolver are separately operated, rework bounded to three with its own deadline, and a rights policy whose recipients include every role.

Role behavior Supported
Rework Up to max_reworks replacements, each naming the buyer's request_rework review of the previous submission, contesting only existing criteria, before rework_due_at. Numbers are contiguous; same-number substitution is a conflict; nothing follows acceptance.
Verification Only the pinned reviewer; every criterion once; the overall verdict must follow from the criteria.
Review Only the buyer, before the review deadline; accept needs passed verification and a timely available delivery receipt.
Unavailable buyer The resolver may record the delivery receipt and accept a timely conforming submission.
Resolver labor-evidence-v1: accept only timely, available, passed work; reject only on a failed verification, established non-delivery, or cancellation with no qualifying delivery; otherwise unresolved. Every known dispute must be assessed; after resolution_due_at only unresolved.
Cancellation Mutual cancellation owes zero only with both parties' cancellations and no qualifying delivery; a buyer cannot cancel delivered conforming work away; acceptance survives later cancellation.
Finals Buyer acceptance, resolver decision, or mutual cancellation, with full/zero/null amounts; supersession only by an assessed resolution and never of an uncontested acceptance; competing finals are a conflict that stops funding.
Obligations A passing check owes nothing. A final acceptance creates an obligation whose collection is unknown until the central receive adapter's receipt is recorded with pay-ledger's record_worker_earned (exact retries idempotent, a second payment refused). A funded acceptance later superseded by rejection is retained as a refund owed; no transfer happens.
Rights perform-and-review-order for recipients only; separate-grant uses need a grant from both buyer and provider.
Recovery Every retained record is journaled atomically; a restart replays the journal through the same checks, including funding. Duplicates replay as duplicates.

Run cargo test -p labor-roles. The fixtures use synthetic keys and operators, synthetic deliverable digests, and fake funding receipts; they do not run the worker's code (that stays with this crate's task owner path).

Native execution and bounded rework

agreement::Agreement and rework::Worker join the four delivery roles to actual protected task execution. This is an embedding API; the frozen Coder commands keep their existing behavior. An agreement must confirm the original signed MKT records before it can open a canonical labor-roles::wire_host. Each participant has its own key, private directory, signed journal, and exclusive writer lock. Wire references retain the hashes of the original bodies, including during restart and duplicate delivery.

A target must explicitly implement coder.labor-context-file.v1 with interface openagents.labor-context-file.v1 and an absolute meta.context_file outside workspace writes. The worker writes only the admitted context manifest and its exact representations there. The task owner's library entry point admits that one file read-only under its expected hash; neighboring files remain inaccessible. Rework preserves the original input, source snapshot, instructions, program, arguments, policy, recipients, logical request, and run. Its new context can append the exact buyer review and permitted prior output or execution records, within the original rights and retention period. It cannot add a new requirement or give a document execution authority.

Worker::dispatch requires the buyer's original CJ event, signed execution linkage, a separate operator grant, and current authority supplied by the host. Attempts have distinct local task identities and consume the finite whole-order wall and output allowances; concurrency is one. A prior attempt must have a known terminal result and a cleared process group before repair can start. Unknown or missing task history never permits another dispatch. The host polls current authority and cancellation while the owner runs and drains it before returning. Exact retries observe the original task. The environment owner must restore the admitted source snapshot between attempts; this worker does not reset arbitrary workspaces.

Worker::submit collects bounded JSON deliverables from the task owner's retained artifacts, saves the submission before transport, and emits actual RUN linkage plus an execution receipt containing hashes and outcome facts. The receipt excludes task prompts and command arguments. rework::verify implements the pinned byte-equality checker in Rust under the independent reviewer's key: it compares the delivered bytes with the expected hash frozen in the original input. Other checker profiles refuse. Passing verification supplies neither acceptance nor payment.

Free agreements remain the default. Paid agreements require Agreement::with_central_receive to bind the receiver separately from the provider payee in the signed order. Worker::record_funding checks that binding and derives the ledger pins from the frozen agreement. Its caller must supply an authenticated central receive adapter's observation. Recording a receipt performs no wallet operation; acceptance stays uncollected until that separate receipt arrives. The existing role book owns disputes, unavailable buyers, resolver decisions, cancellation, competing finals, and refunds owed.

cargo test -p coder-labor -p labor-roles -- --test-threads=1 exercises real local commands over synthetic source, one context-driven repair, separately keyed worker, reviewer, buyer and resolver journals, exact delivered bytes, failed then passing checks, revoked authority, missing task history, wrong grants and receivers, fake funding, and retry/restart. These isolated participants are not independently operated commercial services.

Remaining product work

The supported adapters are bounded local commands producing JSON and the pinned byte-equality checker. General checker execution, arbitrary instruction policies, model coding quality, independently operated commercial delivery, real funding, payout, and complete costs remain separate qualifications. Owner steps are in NEEDS_OWNER.md. Native rework is available through the Rust embedding API; exposing it through openagents labor waits for the next Coder release.