Instawards · Statement of Work · Section 6
Every requirement the Statement of Work names, what satisfies it, and where to check it without taking anyone’s word for it. 2 items are still outstanding and marked as such below.
Issued for this demonstration and reached through the standard Stellar Asset Contract, not Circle’s testnet USDC. A mainnet pilot would use the canonical one.
Evidence asked for: GitHub repository, deployed contract ID, deployment scripts, testnet transaction hashes, explorer links, and automated test results.
The sponsoring wallet is the first project admin and always has reviewer authority. The builder is the only separate required role; additional admin/reviewer wallets are optional. MAX_MILESTONES is 3 and create_engagement rejects a fourth.
All five live in the Milestone struct. The criteria text stays off chain; its SHA-256 is stored, so the wording is fixed at funding time and cannot be edited afterwards.
create_engagement, fund, submit_evidence, approve, hold, release, refund. Approve and release are two separate signatures on purpose: judging the work and moving the money are different acts.
Every value-moving entrypoint calls require_auth on the role recorded in contract storage. Settlement goes through the standard Stellar Asset Contract interface: there is no token contract in this repository, no custom transfer semantics and no signature scheme of our own — the settlement crate's only dependency is soroban-sdk. The asset itself is a testnet USDC issued by this demonstration (issuer GDZZXFY56X2OALF2VUAX4BM4IB4Q6KTMREKDSMEAQ3M33LRHDDRTSHFG) rather than Circle's testnet USDC, so the demo can mint test balances and stay self-contained. A mainnet pilot would use the canonical USDC SAC; that is named as a precondition in the architecture notes, not left implicit.
Building this source produces WASM that is byte-identical to what is deployed, for both contracts the evidence touches. `contracts/settlement` is the current deployment, sha256 c40b9cd7130fe1c56ad54f57f6c8d4d452494237c80fff6a365d9569b65daab2. `contracts/settlement-v1` is the earlier deployment that engagements 0–4 settled on, sha256 3f8f93abe9f2ce9917f85472a41bc3175bc665363410f2373fa8ad9ac8fbb4ff, kept in the repository precisely so the transaction trail below stays checkable. Two commands prove either one — build locally, then fetch the deployed contract off the network and compare. Nothing in the evidence below rests on trusting that the published source is what actually runs.
65 tests, all six categories: test_happy_path_release · test_stranger_cannot_release and test_unsigned_release_rejected · test_release_on_pending_rejected · test_double_release_rejected · test_zero_amount_rejected and test_total_amount_overflow_is_typed · test_early_refund_rejected. Run with `cargo test --package sprintos-settlement`.
Two live testnet engagements are recorded and indexed from the network: #2 covers create, fund, evidence submission, human approval and release; #3 covers create, fund, evidence submission, Hold and deadline refund. Every hash below opens the corresponding Stellar Explorer transaction. Both settled on the earlier deployment CAJUEUOEP6UUNLQ65XOINCUNVBXYPOGNWZC2XZQE7HRV66KTLERPHLND, which is why that contract and its source are still published — the trail has to remain checkable, so it was never discarded when the current contract went up.
Engagement #2 public recordcreate #2 · 0ef5bdb8fund #2 · e5c18614evidence #2 · 2775cd29approve #2 · 9085da84release #2 · 8e368dcfEngagement #3 public recordcreate #3 · 186b71a7fund #3 · 36e54c1bevidence #3 · ea436df2hold #3 · 83227424refund #3 · ae54c14cdemo scripts
Evidence asked for: Advisory report schema, three sample reports, evidence fixtures, screenshots, module tests, report versions, and report hashes.
MAX_CRITERIA and MAX_EVIDENCE are both 5 and enforced by the schema on every write. The six evidence types are exactly the six the SOW names.
All five fields are required by the report schema, plus a report_hash: the SHA-256 of the canonical report with the hash field removed, so a report cannot be altered after the fact without detection. A live report for engagement #2 was generated with score 25, recommendation RevisionSuggested, binding false, and hash sha256:4eb0627f170efe3775a714429a0396ce5e2b19e7f76002df027149200b2f2443.
Generation happens on an explicit request from the reviewer's screen. Evidence retrieval is credential-free HTTPS with private, local and reserved addresses refused; repositories are read through the GitHub API as metadata and never cloned or run.
The contract's ABI accepts no score and has no entrypoint an automated party can call. The boundary is also compile-enforced: a CI job fails the build if the advisory package acquires a Stellar SDK or any signing code.
test_ai_score_100_cannot_release. The public proof page distinguishes the deterministic 100/100 test vector from live human-signed transactions: the report never enters the contract, and there is intentionally no AI payment transaction. Two companions make the point from the other side: test_ai_score_zero_does_not_block_human_approval and test_settlement_works_with_no_advisory_report_at_all — the advisory module is never on the critical path.
01-complete-delivery scores 94, 02-partial-delivery scores 58, 03-insufficient-evidence scores 8. They are assembled from fixed drafts rather than a live model call, so `pnpm --filter @sprintos/advisory fixtures` regenerates them byte for byte and the hashes below can be checked independently.
Engagement #1002 milestone 1 was scored 100 out of 100 by the live module, recommendation ReadyForReview, both criteria met at high confidence, nothing listed as missing. The milestone did not move. It stayed at EvidenceSubmitted, the escrow did not change and the builder was not paid. An automated agent holding a funded Stellar account then called approve and release on that milestone and was refused both times with Unauthorized — it is not a reviewer, and the score it was acting on was never an argument either call could accept. The reviewer then signed approve, and signed release separately, and 60 USDC moved. Same milestone, same evidence, same perfect score: the signature is what changed. The module is not a rubber stamp either — on engagement #1001 it scored the same builder 60 and then 75, asking for more both times.
Engagement #1002the 100/100 reporthuman approve · fb8c4213human release · 823f0d43revision loop on #1001
The reviewer desk for engagement #1002 milestone 1, captured with the report generated: acceptance criteria and submitted evidence each marked as matching the chain, the advisory panel reading 100 / 100 and Ready for Review under an ADVISORY · NON-BINDING heading, and directly beneath it the decision panel headed HUMAN DECISION · BINDING offering nothing but Connect wallet. A perfect score and no way to act on it, in one frame.
Evidence asked for: Public testnet website, sample engagement pages, role screenshots, wallet signing recording, transaction links, documentation, and demo video.
A four-step setup that locks each step until the previous one is complete: repository, milestone plan, roles, then review and fund. Nothing is signed until a final screen that states the milestones can never be edited afterwards.
Each milestone shows its acceptance criteria in full, alongside a typed evidence form. The bundle is hashed and its hash is what the builder signs on chain.
Both documents are re-hashed on the server and the decision buttons stay disabled unless both match the ledger. The reviewer must also tick an attestation that they read the evidence themselves. No score ever enables a button.
Every write is simulated, prepared, and handed to the wallet. The application holds no key and there is no server-side signing path.
wallet.ts — the only place a signature is requestedcontract.ts — simulate, prepare, hand to the wallet
The public engagement page shows all of them, including a settlement log listing every transaction in order with its signer and its explorer link. The contract records what a milestone's state is but not which transaction produced it, so the application keeps that index — and never trusts it: the server re-reads each transaction from the network and decodes the action, the signer and the milestone from the envelope before storing anything.
The public testnet records are live: engagement #2 ends in Released after human approval, and engagement #3 ends in Refunded after Hold and the deadline. Each page shows the ledger state, evidence pointers and indexed transaction trail.
The public docs page now brings setup, workflow, trust model, evidence integrity and API reference together. Architecture, security model, setup and this evidence pack are also written in the repository. A demo video and role screenshots are still outstanding.
The role screenshots are captured — sponsor, builder and reviewer views, the projects board, both public engagement records, the reviewer desk holding a 100/100 report, the evidence pack and the AI boundary proof — and they ship with the submission packet. What is left is one recording covering the full path in a wallet: sponsor funds, builder submits, reviewer reads the advisory report and signs approve and release as two separate signatures. That single recording satisfies the demo video and the signing recording together, and it is the only item in this pack that a person still has to sit down and produce.
Built from fixed drafts rather than a live model call, so regenerating them produces these hashes exactly. A sample that changed on every run would prove nothing.
| Sample | Advisory score | Report hash |
|---|---|---|
| 01-complete-delivery | 94 / 100 | sha256:b2c2aa34b7ebc08630aee808e66aa68a924feba07f6815e985b83a0dd34484fe |
| 02-partial-delivery | 58 / 100 | sha256:a450fb41923d9d8e5b6c289facc137ecc8eaf63e7321e2beaf9f958d741e64b1 |
| 03-insufficient-evidence | 8 / 100 | sha256:e3456346679a9ee970a767bbeaac4530951806a51ef75b527d2ce0bf09fa1604 |
Clone the repository and run these. None of them need a wallet, a key, or an API token.
cargo test --package sprintos-settlementEvery contract test, including the AI-cannot-release testpnpm lint:boundariesThe advisory module cannot reach the chainpnpm testApplication and schema testspnpm --filter @sprintos/advisory fixturesRegenerate the three sample reports and compare hashes