# WorkProof > WorkProof is for City of Espoo talent events. A professional does a short real task from an Espoo company instead of sending a CV. A named person at the company reads the work without the name, scores it from 1 to 5 on each of the task's skills, writes a reason, and chooses Meet or Not now. The name appears only after the professional accepts. AI drafts tasks; it never scores or ranks a person. Tested: 0 of 79 planted identity details reached a reviewer. Key facts: - Built during Junction 2026 (13 to 15 November 2026) for the City of Espoo challenge "Rethinking Recruitment". - Three modes in one app: Looking for work, Hiring, City of Espoo. - Places per task: each task takes 5 to 30 answers (12 unless the company chooses), so an employer can read them all. The company sets the number before it approves the challenge, and each challenge page shows the places left. - A decision names a reviewer registered for the company. A company lists the people who may decide; a name that is not on the list is refused (HTTP 403) until that person adds themselves in one explicit, logged step, and a name that reads as software is refused outright (HTTP 400). This demo has no sign-in, so the name is not verified. - WorkProof has no automated decision feature. A decision is recorded with the name of a reviewer registered for the company and a written reason. This demo has no sign-in, so the name is not verified. - A named reviewer scores the work from 1 to 5 on each core skill of the task and writes why. The total shows out of 10 (the average points × 2), and a task's top work is sorted by these human totals. Software never gives or suggests a number. - Every reviewer reads the same line under every proof: "Personal details are removed by rules before review. Some can remain." No count of hidden details is shown to a reviewer, since a count would hint at a background. - Facts about the job (the work language, a language level, a licence the law asks for) are neither core skills nor set aside: they are kept under "Good to know", in fixed forms. A wish for a native speaker is set aside with "Ask for a language level, not a native speaker." - Table mode is a live loop: a visitor scans the QR code and does a 2-minute task; the host invites the proof with a two-sentence reason; the visitor accepts or declines on the phone. The big screen shows labels and tasks, never free text, and a name only after its person accepted. - A person can decline an invitation; the name stays hidden from that company. - A picture is sent only after the person confirms it shows only the work. A reviewer can report a picture as possibly identifying; it is then removed for every reader. - The city can act: it makes a challenge for a company from its job ad, drafts a reminder to a company with work waiting (nothing is sent) and exports the list of talks as a CSV file. The organiser sees slots and labels, never names. - Each visitor gets a private demo event behind a cookie. A request without that cookie reads the shared demo event and cannot change it. The visitor's private key travels in a request header, never in an address. - No login and no API keys are needed to run the demo. All people and companies are synthetic. - AI drafts tasks and two follow-up questions. WorkProof has no automated decision feature; each decision carries a reviewer's name and a written reason. - Known personal details are removed by rules before anyone reads the work. Rules can miss some; pictures are checked by the person, not by software. Text is redacted by the same rules before it reaches a model. The built-in designer runs without any model. - Made for Espoo's talent events for business and tech people. - Four formats: Choose, Make, Fix, Read. The demo event has 12 challenges from 10 companies. Without an AI key the built-in designer still drafts: 49 professions have their own task today; any other gets the nearest one or a general planning task. - No decision without a reason: every recorded decision carries a written reason, and unanswered work stays visible to the city. Nothing forces an employer to decide. - Checked on 2026-11-14: 1575 of 1575 unit tests pass (npm test); 55 of 55 eval tests pass (npm run eval). ## Numbers, checked on 2026-11-14 - `npm test`: 1575 of 1575 unit tests pass, in 106 files. - `npm run eval`: 55 of 55 eval tests pass, in 7 files. - Task generator: Drafts with a title, a brief, 3 to 5 core skills, minutes and a review guide: 20 of 20 drafts in shape (`npm run eval`, evals/task-generator.eval.ts) - Task generator: Planted biased wishes set aside (age, native speaker, top university): 3 of 3 baited drafts set it aside (`npm run eval`, evals/task-generator.eval.ts) - Task generator: Planted identity strings in published task cards: 0 planted strings found in 47 published cards from 47 needs (`npm run eval`, evals/task-generator.eval.ts) - Blind review: Planted identity strings that reached the reviewer payload: 0 of 79 planted strings found (`npm run eval`, evals/blind-review.eval.ts) - Blind review: Identity forms hidden, first case set: 54 of 54 cases fully hidden (`npm run eval`, evals/blind-review.eval.ts) - Blind review: Identity forms hidden, second case set: 69 of 72 cases fully hidden, 3 known limits (`npm run eval`, evals/blind-review.eval.ts) - No automated decisions: Planted judging phrases rejected by the guard: 70 of 70 judging phrases rejected (`npm run eval`, evals/no-automated-decisions.eval.ts) - No automated decisions: Neutral task phrases let through by the guard: 33 of 33 neutral phrases passed (`npm run eval`, evals/no-automated-decisions.eval.ts) ## Start here - [/try](http://localhost:3000/try): Do a 2-minute task on a phone and see the blind proof a company would read. - [/table](http://localhost:3000/table): Invite that proof with a two-sentence reason, then accept on the phone: only now the name shows on the big screen. - [/city](http://localhost:3000/city): See the answers each employer still owes, and 0 automated decisions. - [Evidence for judges](http://localhost:3000/for-judges): criteria table, evals, limits, architecture, data and privacy - [How it works](http://localhost:3000/how-it-works): the product in six plain steps, what the AI does and never does, fair questions ## Product - [Landing page](http://localhost:3000/): What WorkProof is, Olena's story and the live Espoo map - [2-minute task](http://localhost:3000/try): Do a short task on a phone and see the blind proof a company would read - [Looking for work](http://localhost:3000/seeker): Olena's home: invitation, open challenges, her work - [Challenges](http://localhost:3000/challenges): Every open challenge at the demo event, in four formats: Choose, Make, Fix, Read - [My work](http://localhost:3000/my-work): The person's own work, what was hidden, the reviewer's scores and reason, and a portfolio to share - [Hiring](http://localhost:3000/employer): Halla Supply's challenges, each with its top work by the reviewers' scores and the work waiting in arrival order - [New challenge](http://localhost:3000/company): A job-ad link or one sentence becomes a challenge with 3 to 5 core skills; a person approves it - [Score work](http://localhost:3000/company/review): Read the work without the name, give 1 to 5 points per skill with a written reason, then invite or not now - [City of Espoo](http://localhost:3000/city): Outcomes, the Espoo flow map, process safeguards and audit log - [Table mode](http://localhost:3000/table): Big screen with a QR code: a phone joins the same demo event ## Evidence in code - [src/lib/blind](src/lib/blind): The blind layer: rules remove known personal details before any reviewer or model reads the work; some can remain - [src/lib/guard](src/lib/guard): The no-judgement guard and the protected-attribute checks on every AI output - [src/lib/service/decisions.ts](src/lib/service/decisions.ts): A decision needs the name of a reviewer registered for the company, the reviewer's points for each core skill and a written reason; without sign-in the name is not verified - [src/lib/domain/scoring.ts](src/lib/domain/scoring.ts): One fixed scale from 1 to 5 per skill and the total out of 10; points come only from a named reviewer - [src/lib/domain/places.ts](src/lib/domain/places.ts): Places per task, so an employer can read them all - [evals](evals): The eval suites behind the numbers above ## Code map - [src/app](src/app): Next.js routes: pages and the JSON API under src/app/api - [src/lib/service](src/lib/service): Rules for tasks, submissions, decisions, meetings and Second look; view builders for each mode - [src/lib/blind](src/lib/blind): The blind layer: rules remove known personal details before any reviewer or model reads the work; some can remain - [src/lib/guard](src/lib/guard): The no-judgement guard: rejects scores, ranks and protected attributes in AI output - [src/lib/ai](src/lib/ai): Scripted task designer (default) and Claude and Gemini adapters, all behind the guard - [src/lib/matching/second-look.ts](src/lib/matching/second-look.ts): Second look: compares tasks by shared core skills, never people - [src/lib/voice](src/lib/voice): Voice input: Web Speech API, ElevenLabs or typed; WorkProof stores only the transcript - [src/lib/store](src/lib/store): In-memory store and a private demo copy (sandbox) per visitor - [src/lib/seed](src/lib/seed): The synthetic event: 10 employers, 12 challenges, 62 pieces of work from 36 people, the scores and decisions - [evals](evals): Eval suites: task generator, blind review, no automated decisions, privacy, flow, story ## Limits - Company and city actions have no sign-in. Any caller can act as any company or as the city in the demo; a pilot needs sign-in and ownership checks. - Pictures are not analysed. The person confirms that the picture shows only the work, and a reviewer can report one; a reported picture is removed for every reader. Nothing checks what a picture shows automatically. - AI-written work is not solved. Our untested assumption: follow-up answers about a person's own choices, and a meeting that starts from the work, make AI-only answers easy to notice. This is not measured yet. The product cannot prove who typed an answer. - Impact is not measured yet. Every outcome in the demo is invented data; the first real test is a pilot event. - Reviewing takes employer time. A task takes 5 to 30 answers, but reading still takes a person's time. - Nothing forces an employer to answer. Every recorded decision needs a written reason, and unanswered work stays visible to the city. - The blind layer is rules, not a guarantee. It misses a lowercase name with no cue word, a bare name with no introduction, another person's name, another spelling of the author's name, and part of an employer name that is not on the list. It over-hides a one-word capitalised sign-off and a capitalised value after "name:" outside a code block. - Video upload is off in the demo; seed proofs carry sample clips, visitors answer in writing, by voice or with a photo. - No ESCO skill ids yet; skills come from the project's own vocabulary. - No Tavata or Brella integration. The meeting list exports as a CSV file; nothing connects to an event tool directly. - The demo store is in memory, one private copy per visitor, reset after 12 hours. - Live AI runs only with an API key; without one the scripted task designer is used.