Evidence for judges
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.
Made for Espoo's talent events for highly educated professionals, where a degree from abroad too often goes unread. Built for the City of Espoo challenge, Junction 2026. Demo data. All people and companies are invented. Numbers checked on 2026-11-14.
0 of 79 planted identity details reached a reviewer. 69 of 72 identity forms hidden in a harder second case set; the 3 misses are another spelling of the author's own name, an employer that is on no list, a third person's name in running text.
Check it in 2 minutes
Shaped at the Espoo booth
On 13 November we asked City of Espoo staff if a work task could replace the CV. They had thought of something similar "on a smaller scale" and named three risks. Our answers:
- A company hires only a few. With consent, one proof can reach a second employer with the same core skills (Second look), after 48 hours without an answer or after a Not now.
- Friction must stay low. No login, no account, no CV. The demo challenges take 10 or 15 minutes. The stated length is capped at 30.
- AI can do the task. AI is allowed. Two follow-up questions ask about the person's own choices, and the meeting starts from the work.
The challenge in the City of Espoo's words
How can recruitment and matchmaking events organized by City of Espoo help companies and talent relevantly find and connect with each other, despite AI-generated job search materials and AI-assisted recruitment processes are becoming common?
…solutions that help create stronger signal and less noise throughout the process of registering and attending an event…
…automated profiling or automated decision-making about individuals without human involvement should not be a part of the solution.
How WorkProof meets each criterion
| Criterion | What we built | Where to see it | Where in code | Evidence |
|---|---|---|---|---|
| Impact & Relevance (45%) | Companies register with a short real challenge in one of four formats (Choose, Make, Fix, Read); people answer with work and think aloud while working; a person reviews with known personal details removed and every recorded decision carries a written reason; the city sees each step from challenge taken to scored, invited, talked, follow-up agreed and hired, and the work still waiting on each challenge. |
| Flow eval: every step from task to a meeting both sides confirmed passes (evals/flow.eval.ts). | |
| Innovation & User Experience (35%) | A task instead of a CV; the blind proof with a slider between what was written and what the company reads; the name shown only after the person accepts; Second look shares a proof with a second employer with the same skills, with consent; a 1-minute guided tour and a Show me demo in each view; a 2-minute task on a phone. |
| Story eval: every story stage rebuilds the visitor's own demo event (evals/story.eval.ts); end-to-end run on a 390x844 screen (evals/e2e). | |
| Responsible & Feasible Execution (20%) | AI never scores or ranks people: a guard checks every AI output; known personal details are removed by rules before review; every decision needs a registered reviewer name and written feedback (not verified without sign-in); runs with no keys; request limits; Docker build. |
| Guard: 70 of 70 planted judging phrases rejected; 551 of 551 text fields of drafted tasks and follow-up questions pass; blind layer: 0 of 79 planted identity strings reach a reviewer; 0 automated decisions. |
The brief's recurring pains
| Pain named in the brief | What WorkProof does | Where in code | Evidence |
|---|---|---|---|
| Companies struggle to describe their needs clearly and early enough. | One sentence becomes a task with 3 to 5 core skills; extra wishes are set aside; a person approves it. |
| Task generator eval: 20 of 20 drafts have 3 to 5 core skills; 3 of 3 planted biased wishes set aside. |
| CVs and messages are generated and analysed with AI, so matching rests on synthetic representations. | No CV. The person hands in work, then answers two follow-up questions about their own choices; the meeting starts from the work. |
| Flow eval: two follow-ups about the answer; follow-ups read only the redacted answer (privacy eval). |
| Companies are overwhelmed by large volumes of irrelevant approaches. | Each proof is work on the company's own task; the queue is in arrival order and holds blind proofs only. |
| Queues in arrival order: yes (no-automated-decisions eval). |
| Companies assume there are no suitable candidates in the city's pool. | The city makes a challenge from a company's job ad, and people do it before the company opens it. In the demo, Kide Silicon's challenge already has 20 pieces of work. The company's home data also counts proofs handed in for tasks that ask for the same skills. Counts only, never a list of people. |
| Unit tests in src/lib/service/views/employer.test.ts. |
| Matching should not reinforce bias by nationality, language, education or career path. | Known names, contacts, places, schools, employers and residence status are removed by rules before review, and some can remain; tasks cannot ask for protected attributes. |
| 0 of 79 planted strings reach the reviewer; 54 of 54 and 69 of 72 identity forms hidden. |
| No automated profiling or automated decision-making about individuals. | WorkProof has no automated decision feature: a decision is recorded with a registered reviewer's name, the reviewer's own points for each core skill and a written reason; a guard blocks scores and ranks in AI output; every decision is in the audit log. |
| 70 of 70 planted judging phrases rejected; 0 automated decisions in the audit log. |
| Few hires per company, and a company may not answer. | Nothing forces an answer, so the city sees the answers each employer still owes. After 48 hours without an answer, or after a not now, the proof can go to another employer whose task shares at least 2 core skills, if the person allowed it (Second look). |
| Flow eval: company B sees the proof through Second look; company C without shared skills cannot. |
| The city cannot measure whether events lead to meetings. | Both sides confirm a meeting took place; the city sees answers given, reply time, meetings confirmed and answers owed per employer. |
| Flow eval: both sides confirm the meeting; city totals change and show 0 automated decisions. |
| The event platform may crash when everyone logs in at the start. | Work is done over the days before the event, with no login rush; request rate and body size limits. |
| Privacy eval: the body cap answers HTTP 413 and the rate limit HTTP 429. |
| International recruitment adds language, permit and relocation questions. | Facts the company writes about the job (a work language, a language level, a licence) are kept in fixed forms under "Good to know" on the draft. Each demo company also records its work language, whether Finnish is needed, permit support and relocation help. |
| Set for all 10 demo employers (src/lib/seed/companies.ts). |
| Solutions should minimise personal data processing. | No account and no CV; the person's key stays in the browser; accepting shows the name to that company only, and the organiser sees slots and labels, never names; WorkProof stores only the text of a spoken answer. |
| 0 of 31 public responses carry a talent id; identity hidden until accepted. |
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.
What the AI does and never does
Does
- Drafts a task from a company's one-sentence need, with 3 to 5 core skills. A person approves every company task. Practice tasks are generated without approval and go to no company.
- Writes two follow-up questions about the person's own choices in their answer.
- Every AI output passes the no-judgement guard; on any failure the scripted designer is used.
Never does
- Scores, ranks, rates or recommends a person.
- Receives a person's name or contact field. Text is redacted by the same rules before it reaches a model. The built-in designer runs without any model. Rules can miss some details in free text.
- Decides Meet or Not now. WorkProof has no automated decision feature; a decision carries a registered reviewer's name and written feedback.
- Analyses a voice or a face. A spoken answer becomes text in the browser or once on the server, and WorkProof stores only the text.
The guard is in src/lib/guard/no-judgement.ts. 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.
Evals
On 2026-11-14: npm test ran 1575 unit tests in 106 files, 1575 passed. npm run eval ran 55 eval tests in 7 files, 55 passed. No API keys are needed for either.
| Suite | Check | Result | File |
|---|---|---|---|
| Task generator | Drafts with a title, a brief, 3 to 5 core skills, minutes and a review guide | 20 of 20 drafts in shape | 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 | 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 | evals/task-generator.eval.ts |
| Blind review | Planted identity strings that reached the reviewer payload | 0 of 79 planted strings found | evals/blind-review.eval.ts |
| Blind review | Identity forms hidden, first case set | 54 of 54 cases fully hidden | evals/blind-review.eval.ts |
| Blind review | Identity forms hidden, second case set | 69 of 72 cases fully hidden, 3 known limits | evals/blind-review.eval.ts |
| No automated decisions | Planted judging phrases rejected by the guard | 70 of 70 judging phrases rejected | evals/no-automated-decisions.eval.ts |
| No automated decisions | Neutral task phrases let through by the guard | 33 of 33 neutral phrases passed | evals/no-automated-decisions.eval.ts |
| No automated decisions | Text fields of drafted tasks and follow-up questions that pass the guard | 551 of 551 text fields from 32 designer outputs (20 drafts, 12 follow-up sets) | evals/no-automated-decisions.eval.ts |
| No automated decisions | HTTP status of 2 decisions sent without a reviewer or feedback; stored decisions with a named reviewer | refused: HTTP 400 for a decision without a name, HTTP 400 without feedback; 34 stored decisions all named | evals/no-automated-decisions.eval.ts |
| No automated decisions | Automated decisions in the city totals and the audit log | 0 automated decisions; 0 decision audit lines by a non-human | evals/no-automated-decisions.eval.ts |
| No automated decisions | Decisions signed by software or by a name the company has not registered | refused: HTTP 400 for "AI bot", HTTP 403 for an unregistered name, HTTP 400 for a bot as reviewer; accepted after the explicit step: HTTP 200 | evals/no-automated-decisions.eval.ts |
| Table screen | Names, emails and numbers typed on phones that reach the public big screen | 0 of 10 names, emails and numbers found; extra fields: none | evals/table.eval.ts |
| Consent and privacy | Public responses that carry a talent id | 0 of 31 talent ids found in company and city responses | evals/privacy.eval.ts |
| Consent and privacy | HTTP status for 5 bad pictures, then for 2 clean JPEGs; the description runs through the blind layer | refused: HTTP 400, HTTP 400, HTTP 400, HTTP 400, HTTP 400 for EXIF, a /demo path, PNG, video, 1 byte over 300 kB; accepted: HTTP 200 at 300 kB, HTTP 200 clean | evals/privacy.eval.ts |
| Flow | Full API flow from task to a meeting both sides confirmed | 21 of 21 steps | evals/flow.eval.ts |
| Demo story | Story stages rebuild the visitor's own demo event | 6 of 6 steps | evals/story.eval.ts |
Try it in 2 minutes
- The guided walkthrough: Olena's story from task to meeting, in nine steps.
- A 2-minute task: answer one task and see the blind proof a company would read.
- Looking for work, Hiring and City of Espoo: the three modes.
Architecture
One Next.js app. Pages and the JSON API call the service rules. The rules pass work through the blind layer before anyone reads it (rules remove known personal details; some can remain), check every AI output with the guard, and keep each visitor's demo copy in memory.
Data and privacy
- No account and no CV. The person's private key is kept in their own browser.
- Reviewers and AI models read work only after the blind layer: known personal details are removed by rules, and some can remain. Responses to companies and the city carry no talent id.
- Accepting shows the name and contact to that company only. The organiser sees slots and labels, never names.
- Second look is off until the person turns it on, and can be withdrawn.
- Voice is turned into text; WorkProof stores only the text. Pictures are re-encoded in the browser and the server refuses a JPEG that still carries EXIF data.
- Each visitor's demo copy lives in memory and is dropped after 12 hours.
Synthetic data statement
Every person, company, task, proof and decision in the demo is invented, including Olena Kovalenko and the ten employers of “Espoo Talent Day”. Email addresses use example.org and phone numbers are placeholders. Any likeness to a real person or company is accidental. The seed is in src/lib/seed.
A plain-text summary for language models is at /llms.txt.