Patent and grant preparation tools
Two local, evidence-first tools cover workflows that may eventually require human review or authorized delivery. They preserve their own records when managed capabilities are unavailable and do not treat generated text as authority.
Patent CLI
patent-cli maintains a private JSON matter with inventors, applicants, disclosures, jurisdiction sources, claims, prior art, attached documents, immutable evidence hashes, and claim-support mappings. It can validate readiness and create a deterministic review ZIP plus an exact approval artifact.
git clone https://github.com/wisent-ai/patent-cli.git
cd patent-cli
cargo build --locked
cargo run --locked -- jurisdictions --query "United States"
cargo run --locked -- init \
--title "Local matter" \
--jurisdiction US \
--output "$HOME/.local/share/patent-cli/matter.json"
cargo run --locked -- validate "$HOME/.local/share/patent-cli/matter.json"Optional Brama review and constrained Weles observation or prefill require separately scoped configuration. The CLI does not provide legal advice, decide patentability, establish deadlines, pay a fee, sign a form, or perform a final filing. Patent-office sources and qualified counsel remain authoritative.
Grant CLI
grant-cli maintains its evidence record in the fleet Postgres database grant-cli: official sources, opportunities, organization facts, eligibility checks, application fields, tasks, documents, claims, budgets, reviewer comments, analytics, and deterministic export. GRANT_HOME or --home selects the local directory for fetched source objects and exports; global --json exposes structured automation output.
git clone https://github.com/wisent-ai/grant-cli.git
cd grant-cli
cargo build --locked
GRANT_HOME="$HOME/.local/share/grant-cli" \
cargo run --locked -- --json init
cargo run --locked -- opportunity --help
cargo run --locked -- application --helpOfficial funder sources and applicant-approved facts remain authoritative. Qualification is a preparation aid, export is not submission, and the tool guarantees neither eligibility nor an award. Submission requires a separately documented and explicitly authorized delivery integration.
Control boundary. Grant CLI stores its evidence record in a reachable fleet database and keeps fetched files locally; an unavailable database refuses rather than silently switching to a local ledger. HandToHuman can own a separately commissioned human task, but it does not turn a prepared package into legal approval, patent filing, grant submission, or acceptance.
Why the ledger works this way
HandToHuman describes work and expects a finished deliverable. Each rule below exists because its absence cost us something real on a third-party marketplace, so each one is stated with the failure that produced it. This is the standard our own execution path is held to.
| Clause | Why |
|---|---|
| Direct assignment at a fixed price. A caller who names the work, the deadline, and the price receives a worker. Posting a listing and waiting for applicants is a marketplace feature, not a work API. | An application flow puts an unbounded human decision between the request and the work. On the one humanization we ran this way, 119 people applied, two were accepted, and neither delivered. |
| A funded task keeps its seat until it is delivered. A worker who abandons the task returns the seat; the deposit follows the work, not the attempt. | Two lapsed attempts consumed a settled deposit. The provider then reported status=open with spotsRemaining=1, refused the deposit as already complete, and refused every accept with 402 no remaining seat available. Paid work became unstaffable with no way for the caller to recover it. |
| Proof of human origin, returned with the deliverable. A continuous recording of the writing session, or keystroke evidence, addressed by URL on the task snapshot. | The whole point of commissioning a human is that the output is not model output. Evidence has to arrive with the work, not on request. |
| A verification score the caller can quote. One number, computed by the provider, stating the confidence that a person produced the text. | An attestation checkbox and a video are evidence for a human reviewer. Software integrating the API needs a value it can gate on. Nothing on the current humanization resource carries one. |
| Price quoted from length and deadline. The provider returns the price for a given word count and turnaround; the caller does not guess it. | A caller setting the price by hand either overpays or posts work nobody takes, and cannot compare a two-hour turnaround with a two-day one. |
| Formats beyond plain text. The same envelope for a document, a figure, or a page, distinguished by a format field. | Text was the starting point, never the requirement. A provider whose only format is text forces a second integration for every other artifact. |
| Reputation fields, or none at all. If applications carry a rating and a job history, publish them; if they do not, say so in the schema. | Fields that are always null make every reputation gate reject everyone. Our selection defaults are now derived per task kind for exactly this reason. |
All seven are met here. Not by a provider agreeing to implement them, but by the ledger in this repository: the rate card, direct assignment with a deadline, reassignment that leaves the escrow alone, evidence required at delivery, a measured verification before acceptance, and a rating that only settled orders can move.
Our own execution path
A humanization runs on the ledger in this product: a carded price, direct assignment with a deadline, reassignment that leaves the escrow alone, delivery that must carry its proof, and a verification the caller can gate on. The worker app is the other end of the same loop.
90 cents per 100 words, rounded up, floor 300 cents
× 2.00 under an hour
× 1.50 one to four hours
× 1.20 four to twenty-four hours
× 1.00 one to three days
× 0.85 three days or more
platform fee: 15 percent of the total, taken out of itThe fee comes out of the total the same way Marketplace::release splits an escrow, so the worker_cents in a quote is the number the worker receives. A 648-word rewrite due in a day quotes at 630 cents, of which the writer keeps 536.
handtohuman quote --input related-work.txt --turnaround-minutes 1440
handtohuman market order-fund <order_id>
handtohuman market order-assign <order_id> --worker writer-1 --turnaround-minutes 1440
handtohuman market order-lapsed
handtohuman market order-verify <order_id> --document rewrite.txt --recording session.mp4
handtohuman market order-accept <order_id>- Reassignment does not move money. Measured end to end: a worker held an order past its deadline, the order appeared in
order-lapsed, a second worker took it, and the escrow read345/0/0funded, released, refunded both before and after. The first attempt is kept asexpiredinorder_attempts. - A humanization delivery without its recording is refused —
a humanization delivery needs evidence.recording— and so is acceptance without a verification. - Verification is measured, not asserted. Word count against the commissioned length, how much of the source vocabulary the rewrite left behind, session length, whether it landed inside the deadline, and the SHA-256 of both artifacts. A returned copy of the source scores zero change and fails as
this is not a rewrite. - The worker app closes the loop.
GET /v1/mobile/tasksshows the assignment with its deadline,POST /v1/mobile/tasks/{id}/deliveruploads thedocumentandrecordingparts straight into the evidence the ledger requires, andPOST /v1/mobile/payoutsrequests the balance once the order is accepted.
Joining, paying in, getting paid
The arithmetic was real before this; the two ends were not. A supplier could not join without an operator editing a configuration file, and a balance was credited on somebody's word. Both ends are the product's own now.
curl -X POST -d '{"display_name":"Anna Kowalska"}' https://…/v1/signup
handtohuman market worker-register --name "Anna Kowalska"
handtohuman market token-list <account> handtohuman market token-revoke <token_id>
handtohuman market payment-intent brand --amount-cents 630 --purpose "rewrite"
handtohuman market payment-settle <intent> --provider-reference stripe_pi_…
handtohuman market offers --kind humanization- A supplier joins themselves. Signup creates a worker account and returns a bearer token once. Only its SHA-256 is stored, so a copy of the ledger cannot be replayed as a login, and revocation ends a session on the next request. The worker API reads identity from the ledger; there is no token map in the environment.
- Money in is an intent and a settlement. An intent credits nothing. Settlement credits the balance and demands the provider's own reference for the movement, unique across the whole ledger.
- Browsing exists.
market offerslists active offers with units left, so an order does not need an offer id passed around by hand.
Measured, one transaction end to end. A writer signed up over HTTP and their token's plaintext appears nowhere in the database; a 630-cent intent credited only on settlement and refused a replayed reference; the buyer browsed the offer, ordered, funded, and assigned with a deadline; the writer saw the task in the app and uploaded the document and recording; verification passed at 3675 basis points changed inside the deadline; acceptance paid 536 cents to the writer and 94 to the platform; the payout was requested from the app and completed against a transfer reference. A revoked token stopped authenticating on the next request.
Money out is POST /v1/mobile/payouts from the worker's app, reserving their balance against the destination recorded on their account: a payout request does not restate where the money goes, and a worker who has named no destination is told which endpoint names one.
The payment provider
Settlement and payout require the provider’s own answer. HandToHuman reaches Stripe through wisent-integrations at STADO_INTEGRATION_API_URL with HANDTOHUMAN_INTEGRATION_TOKEN or the Stado integration bearer field token. For the latter, the client resolves the Skarbiec route as consumer handtohuman, then reads with a dedicated consumer grant, not Stado’s store administrator. Its Stado binary, configuration and grant share HANDTOHUMAN_FLEET_HOME when set, else HOME. Without Stado, an owner-only file named by HANDTOHUMAN_STRIPE_KEY_FILE supplies a direct Stripe key. The CLI reports the failed route or credential read and its cause.
handtohuman market payment-checkout <intent> --success-url https://example.com/paid --cancel-url https://example.com/cancel
handtohuman market payment-sync <intent> # credit only if Stripe says paid
handtohuman market worker-connect <worker> --country PL --email pisarz@example.com --refresh-url https://example.com/retry --return-url https://example.com/return
curl -X POST -H "Authorization: Bearer …" -d '{"country":"PL","email":"…"}' \
https://…/v1/mobile/me/connect # the same, from the worker's app
handtohuman market payout-readiness <worker> # payouts_enabled, transfers, due
handtohuman market payout-send <payout> # transfer it, close it
handtohuman market payments-doctor --worker <worker> # can money move at all- Money in. A checkout is opened for exactly the intent's amount and its id and pay-here URL are stored on the intent; nothing is credited. Sync reads that session back and credits only on
payment_status: paid, using Stripe's PaymentIntent id as the ledger's unique provider reference. A session that collected a different amount refuses instead of crediting it. - Becoming payable. A worker cannot invent a destination. The platform creates their Express connected account, records it as their payout destination, and returns a hosted onboarding page where Stripe collects identity and bank details. Those links are single-use, so a new one is minted every call while the account is created once.
- Money out. A transfer goes to the destination recorded on the payout when it was requested, and the payout closes carrying the transfer id. A destination that is not a connected account is refused before any call; an account whose onboarding is unfinished is refused by Stripe with 402
insufficient_capabilities_for_transfer.
One command says whether money can move. market payments-doctor reports the credential source, provider mode, platform balance and, for a named worker, payout readiness. If a Stado read fails, blocked_by names the directory or delegated credential operation, its exit status and Stado’s error. It creates nothing and carries no fee.
Provider refusals stay visible. A wrong bearer or key is reported by the provider rather than accepted as a healthy configuration. A missing local bearer names the failed Stado read or the environment variable; local guards refuse before a provider call.
A credential is sanitised where it enters. Surrounding whitespace and trailing escaped newline sequences are stripped once by the payment resolver.
Measured against the live account. payments-doctor answers can_move_money: true with the key resolved from the vault and mode: live. A Checkout Session for a 630-cent intent opened at checkout.stripe.com in live mode, and payment-sync read it back as status: open, payment_status: unpaid and credited nothing — ledger untouched, balance zero, order still created.
Every way money can come in, and which the provider allows. Three, each attempted against the live account rather than predicted. payment-checkout gives a hosted page the card holder enters a card on, and it works — a live session for the 630-cent intent exists and sync reads it back unpaid. payment-charge charges a card the buyer already gave us, off-session and with no page; attempted for real on the one saved card, the issuer answered 402 card_declined, which is the card's decision and not this ledger's, so the command repeats it and names the page. A balance top-up is refused here with Your default eur bank account has not been verified. A fourth path needs no person at all: Weles drives the hosted page on the registry's browser host with the workspace purchase card. Measured on the live session — contact email filled, the Card method selected among iDEAL, Bancontact and EPS, Link declined, card filled, form submitted — the issuer answered Your credit card was declined because of insufficient funds. Try paying with a debit card instead. Giving the marketplace a different card is one command: the card is one Skarbiec item holding number, expiry, CVC, postal code and name, replaced with skarbiec set <card item> reading the values on stdin, and a job receives it as --secret-env TOPUP_CARD_JSON=<card item>#value — one variable the agent injects and redacts from the job's output, so a card number never reaches a command line, a queue row or a log. So the mechanism has no gap: a card can be charged from a page, from a saved method, or by the fleet, and each path reports the provider's own answer. What none of them can supply is money on the instrument. Nothing after a successful payment needs a person either: settlement, escrow, assignment, verification and payout all run from the ledger.
Paying ourselves needs no Connect. A transfer to a third party does, and worker-connect returns Stripe's own sentence — You can only create new accounts if you've signed up for Connect — until that is enabled. But an operator writing on their own marketplace is not a third party: a payout destination of stripe:platform-bank moves the platform's own balance to its own bank with POST /v1/payouts, which Connect does not gate. Probed live, a one-cent payout refused amount_too_small and a 536-cent one balance_insufficient — the endpoint, the key's scope and the bank are present, only funds are missing.
A payout leaves in the currency it was earned in. The provider settles in the account's own currency, and this account is Polish and settles EUR, so a USD payout would refuse forever with a message about a low card balance. payout-send compares the two first and says it plainly: the platform holds 0 EUR available, and this payout is 536 USD: pay in and settle in the currency you pay out in. The order that had been staged in USD was withdrawn with market order-cancel — which returns the capacity it reserved and refuses once money is in escrow — and restaged in EUR.
Campaigns and performance payout
A single order buys one deliverable. A creator campaign is a different shape: one brief, one budget, several creators, and a payout that depends on what the content did rather than on the fact that it was filmed. Managed creator networks sell exactly that, behind a sales call and a monthly retainer. The ledger expresses it as an envelope and a measured bonus.
handtohuman market campaign-create brand --kind ugc-video --brief brief.txt \
--budget-cents 60000 --spots 3 --bonus-per-1k-cents 20 --bonus-cap-cents 5000
handtohuman market campaign-order <campaign_id> <offer_id> --request req.json
handtohuman market order-measure <order_id> --metric views --value 240000 \
--source "tiktok business api" --reference https://…/video/123
handtohuman market order-bonus <order_id>- The budget is an envelope, not a promise. Each order inside a campaign reserves its total plus the bonus cap. An order that would reserve past what is left is refused with both numbers in the sentence, spots are counted, and a mismatched kind or currency is refused.
- The bonus is released against a recorded measurement, or not at all.
order-measurestores the metric, the value, who read it, and where it can be read again.order-bonuscomputes the earned amount at the campaign's rate, caps it, funds it from the remaining budget, and refuses a second release on the same order. - We do not claim to measure virality ourselves. A bonus is exactly as trustworthy as the source named beside it: a platform API key makes that source a machine, a person reading a dashboard makes it a person, recorded as one.
Measured. A three-spot campaign at 60000 cents booked three 15000-cent orders, refused the fourth on spots, and refused a 16000-cent campaign that could not cover one order plus its bonus cap. 240000 views at 20 cents per thousand paid 4800 cents, 4080 of it to the creator, and the second release attempt was refused.