Inspiration

A freelancer writes a five-page brief. Three weeks in, the client asks for Google login and "throws in" copywriting. Nobody can prove what was agreed, so the freelancer eats the cost — or the relationship ends. Contracts don't settle that argument, because the argument is about interpretation, not wording.

ClearDeal started from one question: what would a contract look like if every claim about it had to produce evidence, or admit it had none?

What it does

The brief becomes a table of requirements, each marked explicit or inferred. An explicit row must quote the sentence that justifies it, or it is rejected before it reaches the screen.

The model drafts an agreement whose milestones must equal the budget to the cent. If they miss, the draft is discarded and nothing is written.

Two signatures need two principals: the owner signs as freelancer, and the client role only opens for the account named on the invitation — a single-use link that carries that client's own session, never the freelancer's.

Then a new ask is classified against the approved scope, with a citation that must resolve to a real section and a quote that must appear inside it. A quote that is reworded, stolen from another section, or cites a section that doesn't exist is downgraded, and the reason is shown.

Payment follows the same rule: the amount is read from the milestone row, never from the request.

How we built it

FastAPI, SQLAlchemy and Alembic on the back, one static page of vanilla JavaScript on the front, Gemini for the three language steps.

The interesting part is the constraints. Every model call goes through a JSON schema and then a validator that rejects what a schema cannot express: arithmetic that doesn't add up, a citation whose quote is not in the cited section, confidence offered as a number. Nothing is stored until it passes.

325 tests at 92.6% coverage, run by one command that also lints and does a migration round trip. A second command checks that the skills used on a change were declared, because a rule that exists only in prose is a rule nobody can fail.

Payments use PayPal Orders v2, sandbox, with webhook verification.

Challenges we ran into

Trusting the model was the trap. Early versions accepted plausible output; the fix was to make the server the skeptic — validate, downgrade, refuse.

The demo had its own honesty problem: two signatures need two sessions, so the recording runs two isolated browser contexts and cuts them together. A second tab would share cookies and quietly sign the freelancer out.

We lost two takes to a stale environment variable shadowing .env — the app was calling the provider with an invalid key, and the error surfaced three layers away. And the deployed SQLite resets on every deploy, so demo state has to be re-established rather than assumed.

Accomplishments that we're proud of

The refusals are the product, and they are real: a draft thrown away because the milestones missed the budget, and OUT_OF_SCOPE with the sentence that proves it.

A single command answers "is it real" — gate, lint, migration round trip, 325 tests — and prints VERIFIED or fails.

The two-principal rule is enforced on the server, so hiding the freelancer's controls in the client's view is decoration, not the mechanism.

A real sandbox order was created on camera during the recording.

What we learned

Verification is a feature, not a test suite. The demo is worth nothing if the only thing it can show is a happy path.

Also: reproducible demos are engineering. Every take that failed taught us something about the product — the sign-in form rejecting a returning user, the client's sign button never being revealed.

What's next for ClearDeal

Approving a change into a new version — that needs a pricing decision before it needs code. Then escrow and multiparty splits, which need PayPal partner approval. And a persistent database, so the deployed demo stops forgetting itself.

Built With

Share this project:

Updates

Submission history