# Wbso

> Registreer WBSO-uren via een gesprek. Gebruik wanneer de gebruiker uren wil schrijven, vraagt naar WBSO-uren registratie, of zegt "ik ga uren boeken". Optioneel: geef een urenargument mee om direct dat aantal uren voor te stellen.

- Skill: `wbso-ai/wbso` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add wbso-ai/wbso`
- Raw SKILL.md: https://api.skillmd.com/api/skills/wbso-ai/wbso/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: wbso-ai (https://skillmd.com/u/wbso-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/wbso-ai/wbso

---


# WBSO uren registreren

Help de developer hun WBSO-uren te boeken via een kort gesprek. Doe een
voorstel op basis van wat je weet, vraag pas door waar het echt nodig is.

## Vraagstijl

Gebruik standaard plain tekst. Dat werkt in Claude Code, Codex en andere
Agent Skills-clients en houdt de flow snel.

Als de client een gestructureerde vraag/keuzelijst ondersteunt, gebruik die
alleen voor echte gesloten lijsten. Houd je dan aan:

- **Max 4 opties per vraag** — meer betekent: groepeer ("Iets aanpassen")
  en stel daarna een vervolgvraag
- **Geen handmatige "Anders"-optie** als de client die automatisch toevoegt
- **`header` ≤ 12 tekens** (bv. `"Boeking"`, niet `"Boeking bevestigen"`)
- **`label` 1-5 woorden** — kort, scanbaar
- **`description` is uitleg** — niet de keuze herhalen

## Argument: snelboeken

Als de gebruiker een urenargument meegaf (bijv. `/wbso 4` in Claude Code
of `4` bij expliciete skill-invocation in Codex), gebruik dat uren-getal
als totaal voor de dag op het voorgestelde project. Sla in Stap 3 de
"Andere uren"-vraag over — vraag alleen het project + de WBSO-bevestiging.

Als er geen argument is meegegeven, volg de normale flow.

## Werken via de `wbso` CLI

Elke skill shipt een **self-contained** `scripts/wbso` naast `SKILL.md`
(canonical bron: `packages/wbso/bin/wbso`, gesynchroniseerd via
`bin/sync-wbso-cli`). Dat werkt na plugin-install én na
`npx skills add wbso-ai/skill`.

Claude Code zet plugin-root `bin/` ook in `$PATH` (via
`${CLAUDE_PLUGIN_ROOT}/bin/wbso`). Na `npx skills add` staat alleen de
skill-map geïnstalleerd — daarom shipt elke skill een self-contained
`scripts/wbso`. Resolve in deze volgorde:

```bash
WBSO_CLI="$(
  command -v wbso 2>/dev/null ||
  { [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && [ -x "${CLAUDE_PLUGIN_ROOT}/bin/wbso" ] && printf '%s\n' "${CLAUDE_PLUGIN_ROOT}/bin/wbso"; } ||
  find \
    "$PWD" \
    "$HOME/.claude/skills" \
    "$PWD/.claude/skills" \
    "$HOME/.cursor/skills" \
    "$PWD/.cursor/skills" \
    "$HOME/.agents/skills" \
    "$PWD/.agents/skills" \
    "$HOME/.codex/skills" \
    "$HOME/.codex/plugins/cache/wbso-ai/wbso" \
    "$HOME/.codex/plugins/cache" \
    -path '*/scripts/wbso' -type f 2>/dev/null |
  sort -V | tail -1
)"
test -n "$WBSO_CLI" || { echo "WBSO CLI niet gevonden"; exit 127; }
"$WBSO_CLI" context
```

In de snippets hieronder betekent `wbso` dus: `wbso` uit `$PATH`, of
`"$WBSO_CLI"` als je de fallback moest gebruiken. Alle API-calls gaan
via deze CLI; geen inline curls meer. De CLI laadt zelf
`~/.config/wbso/.env.local` (dev-override) en `~/.config/wbso/config`
(api-key + email), dus je hoeft niks te sourcen.

Beschikbare subcommands:

- `wbso signup --first-name X --last-name Y --email Z --company-name W`
- `wbso login --api-key Y` (email wordt uit de respons gehaald)
- `wbso context [--date YYYY-MM-DD] [--user-email X]`
- `wbso track-time --project SLUG --date YYYY-MM-DD --duration N [--user-email X]`
- `wbso untrack-time --id N`
- `wbso evidence --title X --description Y --date YYYY-MM-DD [--external-id ID] [--user-email X]`
- `wbso untrack-evidence --id N`
- `wbso suggest-project --description X`
- `wbso feedback --message X --category bug|idea|question|compliment|complaint|other [--context JSON]`

`wbso evidence` is idempotent per dag: zonder `--external-id` gebruikt het
een vast id `wbso-onderbouwing-<user>-<datum>`, dus opnieuw boeken voor
dezelfde dag werkt de bestaande onderbouwing bij in plaats van een
duplicaat te maken. Het `id` voor `untrack-evidence` komt uit de
JSON-respons van `wbso evidence`.

Output:

- `wbso context` retourneert **markdown met XML-tags** (verhaal-vorm,
  geoptimaliseerd om te lezen — kijk naar `<status>`, `<project>`,
  `<submission_owners>` en `<alert>` tags)
- `wbso signup`, `wbso track-time`, `wbso evidence`, `wbso untrack-time`,
  `wbso untrack-evidence`, `wbso suggest-project` retourneren **JSON** van
  de server (de skill leest die direct)
- `wbso login` print `ok (<email>)` bij succes

## Stap 0: Login check via `wbso context`

Open de sessie met:

```bash
wbso context
```

De respons is markdown met XML-tags. Begint 'ie met
`<status>not_logged_in</status>`? → doorloop de setup-flow hieronder,
en run daarna `wbso context` opnieuw. Begint 'ie met `<status>ok</status>`?
→ ga direct door naar Stap 2; je hebt alle context al en hoeft Stap 1
niet meer apart te doen.

### Setup-flow (alleen bij `not_logged_in`)

Stuur in één plain-tekst-bericht een warme introductie en de eerste vraag.
Voor de openingsbeurt is vrije tekst beter; de agent leest het antwoord van
de gebruiker dan natuurlijk:

> *"Welkom bij WBSO.ai 👋 Ik help je je WBSO-uren registreren via een
> kort gesprek. Je vertelt waar je vandaag aan hebt gewerkt, we kijken
> samen of het WBSO-waardig is, en ik boek het direct in."*
>
> *"Eerst nog even setup: heb je al een account, of zal ik er eentje
> aanmaken?"*

Wacht op de reactie van de gebruiker (vrije tekst). Interpreteer:

- "ja" / "ik heb al een account" / e-mailadres → **Bestaand account**
- "nee" / "maak aan" / "nieuw" → **Nieuw account aanmaken**

Bij twijfel: vraag kort terug.

#### Bestaand account

Volg de gebundelde `wbso-auth` skill — die opent de API keys-pagina in de
browser, vraagt de gebruiker de key te plakken, en slaat 'm op in de
config. Run daarna `wbso context` opnieuw zodra de auth-flow klaar is.

#### Nieuw account aanmaken

Volg de gebundelde `wbso-signup` skill — die vraagt naam/email/bedrijf in één
keer, maakt het account aan, opent de browser voor de wizard, en wacht
tot de eerste projecten aangemaakt zijn. Run daarna `wbso context`
opnieuw.

#### Config schrijven

`wbso signup` en `wbso login` schrijven de config zelf in
`~/.config/wbso/config` (mode 600). Geen handmatige stappen nodig.

## Stap 1: Context ophalen

```bash
wbso context
```

Voor een specifieke datum: `wbso context --date 2026-05-14`. Voor een
collega (alleen als de gebruiker dat expliciet wil):
`wbso context --user-email collega@bedrijf.nl`.

### Voor wie boek je?

Een API key is gekoppeld aan één gebruiker — alle calls werken namens
die persoon. Bij `time_entries` en `evidence` mag je optioneel een
`user` (POST) / `user_email` (POST/GET) parameter meesturen om voor
een collega te werken:

- **Submission_admin** of **tech_contact**: kan voor elke collega
  binnen het bedrijf boeken of onderbouwing toevoegen — net als op
  WBSO.ai.
- **S&O medewerker** (geen rol): mag alleen voor zichzelf — een
  afwijkende `user`-param geeft `403 Forbidden`.

Stuur de param dus **alleen mee als de gebruiker expliciet voor een
collega wil boeken**. Anders weglaten en de standaard (key-eigenaar)
gebruiken.

Velden in de respons:

| Veld | Inhoud |
|------|--------|
| `instructions` | WBSO-criteria. **Leidend voor je inschatting.** |
| `commit_score_prompt` | Hoe commits gescoord worden. Toon op verzoek. |
| `alert_rules` | Alle regels die alerts kunnen triggeren. Gebruik om **vooraf** te waarschuwen, niet alleen achteraf na een POST. |
| `projects` | Actieve projecten op deze datum. |
| `time_entries` | Wat er al geboekt staat vandaag. |
| `commits` | Commits van deze user vandaag met score (0-10). |
| `events` | Agenda-items vandaag. |
| `evidence` | Bestaande onderbouwing. |
| `submission_owners` | De aanvraag-verantwoordelijke(n) van het bedrijf, met naam en rol. Gebruik de naam bij de "mogelijk nieuw project"-flow. |

### Lokale signalen — al meegenomen door `wbso context`

`wbso context` plakt automatisch lokale XML-secties onder de
server-respons als je cwd een git-repo is of als er agent-sessies van
vandaag zijn:

- `<git_commits_today>` — commits van vandaag met SHA, auteur,
  tijdstip, full message en bestand-diffstat
- `<claude_user_prompts_today>` — alleen door de gebruiker zelf
  ingetypte prompts uit Claude Code sessies van vandaag (geen
  assistant-antwoorden, geen tool-calls)
- `<codex_user_prompts_today>` — alleen door de gebruiker zelf
  ingetypte prompts uit Codex sessies van vandaag in deze repository
  (geen assistant-antwoorden, geen tool-calls)

Blijft volledig lokaal — `wbso context` haalt server-data via HTTPS,
lokale signalen leest 'ie uit `git log`, `~/.claude/projects/` en
`~/.codex/sessions/`.
Alleen jouw uiteindelijke conclusie (project + uren + datum + evt.
onderbouwing) gaat naar de API.

### Vooraf checken: alert-regels

Loop de `alert_rules` uit de context af en check ze tegen het voorstel
dat je gaat doen. Als een regel zou triggeren bij dit voorstel, neem
de waarschuwing op in Stap 3 voordat je boekt:

- `weekend` → klopt het echt dat je vandaag werkt?
- `over_8_hours` → 8+ uur is een rode vlag bij RVO-controle (zie
  `instructions`)

`missing_evidence` / `low_commit_scores` waarschuw je **niet** vooraf
— onderbouwing is optioneel en wordt na het boeken één keer neutraal
aangeboden (zie Stap 4). Niet pushen.

## Stap 2: Synthese — kies wat nog NIET geboekt is

De gebruiker heeft deze skill gestart om iets te boeken dat er nog niet
staat. Vermijd dus voorstellen die het al-geboekte herhalen.

**Doe altijd een gok, ook bij twijfel.** Stel nooit losse vragen
("welk project?", "welke fase?", "hoeveel uur?") als opening — bouw
één compleet voorstel en laat de gebruiker corrigeren via Stap 3.

Vorm een voorstel:

- **Project**: kies een actief project uit `projects` waarop nog
  ruimte is. Volgorde van voorkeur:
  1. Project waarop activiteit (commits, reflog branch-namen, agenda,
     agent-sessieprompts) wijst en dat **nog niet vandaag is geboekt**
  2. Een ander actief project waar activiteit op zit, ook al staan er
     al uren — propose dan een **update** naar een hoger totaal
  3. Bij twijfel: het eerste actieve project waar vandaag nog geen
     uren op staan (alfabetisch op `title`)
  4. Pas als alles al geboekt staat én er geen onbenutte activiteit
     is: pivot naar de "Alles al geboekt"-flow (zie hieronder)
  5. Is het werk WBSO-waardig maar past het bij **geen enkel** actief
     project? Boek geen uren — pivot naar de "Mogelijk nieuw
     project"-flow (zie hieronder)
- **Fase**: leid af uit commits, reflog, agenda of agent-prompts. Bij
  twijfel: de eerste fase in `phases`
- **WBSO-toets**: werk op een actief project is standaard gewoon
  WBSO-waardig — geen oordeel nodig in het voorstel. Voeg alleen een
  korte WBSO-notitie toe als het werk duidelijk in een niet-S&O
  categorie valt (design/UI/UX, marketing/sales, administratie/
  management, documentatie, regulier onderhoud, configuratie/deployment,
  leren/cursus); zie `instructions`. Splits niet in "deels"
- **Uren**: doe **geen** schatting uit losse pols. Gebruik alleen:
  1. Het urenargument als dat is meegegeven
  2. De duur van een eenduidig agenda-block dat overeenkomt met de
     activiteit
  3. Anders: laat 't veld open en vraag de gebruiker.
  Tel commits niet om naar uren — code-volume zegt niks over
  doorlooptijd, en RVO accepteert geen geschatte uren zonder bewijs.

## Stap 3: Toon voorstel en vraag bevestiging

### Tone

Doelgroep is de developer zelf. Technische taal is prima. Wees
**zo kort mogelijk**: end-of-day wil de gebruiker geen audit lezen,
alleen een 2-regel proposal en een Enter-druk.

Geef je WBSO-inschatting **één keer**, in één zin. Heeft de gebruiker
eenmaal gekozen (boeken, melden, overslaan): voer uit en bevestig
beknopt — herhaal het advies niet en plak er geen nieuwe
kanttekeningen aan. Niet meedenken waar het niet gevraagd is.

**De gebruiker boekt, jij stelt voor.** Schrijf niet "ik boek dit
niet" of "ik laat dit weg" alsof je zelf de actie uitvoert. Schrijf
in de derde persoon over de uren: *"Deze commits tellen niet als
WBSO en zitten niet in het voorstel"*, niet *"die boek ik niet"*.

### Geen slug, geen ID, geen HTTP-codes in UI

Alle gebruiker-zichtbare tekst (voorstel, keuzelijst-labels,
descriptions, previews, na-bevestigingen) gebruikt **alleen
projecttitels**. Geen slugs, time_entry-IDs of HTTP-statuscodes.
Gebruik die alleen intern in API-calls.

### Voorstel: compact

Eén regel context (alleen als nuttig), dan het kern-blok — geen
iconen, geen bullet-lijst. Standaard is dat gewoon `<fase> op
<project_title>.` zonder WBSO-oordeel. Voeg **alleen** een tweede
regel toe als het werk duidelijk in een niet-S&O categorie valt:

```
<optionele één-regel context, alleen als update of als al iets staat>

<fase> op <project_title>.
<alleen als niet-S&O categorie: één neutrale zin, bijv. "Dit is
designwerk, dat valt doorgaans buiten S&O — jouw keuze.">
```

Alleen als de uren-context **expliciet** uit een urenargument of een
agenda-block volgt, vermeld je die: `<uren> uur op <fase>`.
Anders: laat de uren weg en vraag ze later expliciet.

Voorbeeld zonder uren-context (standaard, geen WBSO-oordeel):

```
Classifier en routing op AI-assistent voor klantenservice.
```

Voorbeeld mét uren-context (agenda-block van 2u of urenargument `2`):

```
2 uur op Classifier en routing (AI-assistent voor klantenservice).
```

Voorbeeld mét niet-S&O notitie (alleen bij duidelijk design/marketing/
admin/docs/onderhoud-werk):

```
2 uur op Designsysteem (AI-assistent voor klantenservice).
Dit is designwerk, dat valt doorgaans buiten S&O — jouw keuze.
```

Voorbeelden van wanneer een context-regel mag:
- *"Je staat op 4 uur dit project — voorstel om door te zetten naar 8."* (update)
- *"Vandaag al 5 uur op andere projecten geboekt."* (alleen als nieuwe boeking dat totaal duwt richting >8)

Anders: laat 'm weg.

### Bevestiging als plain tekst

Print het voorstel als plain tekst-bericht, gevolgd door een korte
vraag op één regel. Gebruik hier geen modal of keuzelijst; die verbergt
de chat-geschiedenis en voelt zwaar voor een end-of-day boeking.

Voorbeeld zonder uren-context:

```
Classifier en routing op AI-assistent voor klantenservice.

Hoeveel uur heb je hieraan gewerkt?
```

Voorbeeld mét uren-context (urenargument `2` of agenda-block):

```
2 uur op Classifier en routing (AI-assistent voor klantenservice).

Registreer dit? (ja / pas aan / niet)
```

Wacht op vrije tekst. Interpreteer ruim:

- Een getal ("3", "4 uur", "half uurtje") → vul in en vraag dan
  bevestiging opnieuw
- "ja", "yes", "boek", "ok", "👍", lege regel → POST de boeking
- "pas aan", "ander project", "andere uren", "minder uren", "niet WBSO" →
  pas het voorstel direct aan op het genoemde veld en bevestig opnieuw
- "nee", "niet", "annuleer", "skip" → geen boeking, stop

Bij "pas aan" zonder specificering: vraag kort *"Wat moet anders —
project, uren of WBSO-inschatting?"* als vrije tekst.

Bij vermeld project/uren: pas in één keer aan en toon nieuw voorstel.

### Wel keuzelijsten voor expliciete keuzes

Een gestructureerde vraag of keuzelijst mag wél in twee gevallen, als
de client die ondersteunt. Als dat niet beschikbaar is, stel dezelfde
vraag als plain tekst:

- **"Alles al geboekt"-pad**: max 3 actieve projecten + *"Ik ben klaar
  voor vandaag"*
- **"Geen signaal"-pad**: max 3 actieve projecten als suggesties

In alle andere gevallen: plain tekst.

### Alles al geboekt + geen onbenutte activiteit

> Vandaag al <X> uur geboekt. Geen nieuwe activiteit. Wat nu?

Keuzelijst met max 3 actieve projecten als labels + *Ik ben klaar voor
vandaag*. Voeg alleen "Anders" toe als de client geen vrije-tekstoptie
aanbiedt.

### Geen signaal? (commits, reflog, agenda, agent-sessies allemaal leeg)

Keuzelijst met max 3 actieve projecten als suggesties (label = titel,
description = uren-stand). Voeg alleen "Anders" toe als de client geen
vrije-tekstoptie aanbiedt. Bij keuze van een project: ga terug naar
Stap 2 met die context. Bij Anders/vrije tekst: vraag wat ze deden en
synthetiseer.

### Mogelijk nieuw project? (WBSO-waardig werk, geen passend project)

Het werk lijkt WBSO-waardig, maar past bij geen enkel actief project uit
`projects`. **Boek dan geen uren** — uren kunnen alleen op een
geregistreerd project. Stel voor het mogelijk nieuwe project te melden
bij wie de aanvraag beheert.

Pak de naam uit `<submission_owners>` en spreek die bij voornaam aan,
plain tekst:

```
Het lijkt erop dat je werk hebt gedaan dat nog niet binnen een
geregistreerd project valt. Wil je dat ik Koen (Aanvraag beheerder)
laat weten dat er mogelijk een nieuw WBSO-project is?
```

- **Ja** → vraag kort waar het project over gaat (1-2 zinnen: technisch
  knelpunt + aanpak), dan:

  ```bash
  wbso suggest-project --description "<wat de gebruiker zei>"
  ```

  De respons bevat een `message`, bijvoorbeeld *"Doorgegeven aan de
  aanvraag-verantwoordelijke."* Geef die boodschap kort terug en stop
  daarna. Voeg **geen** WBSO-beoordeling of kanttekening over het
  gemelde werk toe; de aanvraag-verantwoordelijke weegt het.
- **Nee** → respecteer dat, er gebeurt niets. Geen boeking.

Staat er niemand in `<submission_owners>`: noem geen naam, maar bied de melding
nog steeds aan ("je WBSO-beheerder").

## Stap 4: Boeken + alerts

```bash
wbso track-time --project "<slug>" --date "<YYYY-MM-DD>" --duration <hours>
```

Voor een collega: voeg `--user-email collega@bedrijf.nl` toe.

Status: `201` created; `200` updated (idempotent op user+project+date);
`400` bad input; `401` key ongeldig (doorloop setup-flow opnieuw); `403` user
mag geen uren boeken op dit bedrijf; `404` user/project niet gevonden;
`422` jaar afgesloten of validatiefout (geef letterlijk terug); `429`
rate limit (60/min). HTTP-codes nooit naar gebruiker — vertaal naar
mensentaal.

### Bevestiging (kort)

Standaard: één regel + alerts indien aanwezig.

```
✓ Geboekt — <uren> uur op <project_title>.
```

Géén "Vandaag staat nu...", géén dagtotaal, géén dump van de respons.
Tenzij er alerts zijn (zie hieronder).

Lees `alerts` uit de respons en geef die kort terug. **Spreek over
"onderbouwing"**, niet "evidence" — dat is interne API-naamgeving.

Alerts handel je af met **plain-tekst vragen**, niet met keuzelijsten.
Gebruiker antwoordt vrij, skill interpreteert.

### `missing_evidence`

Onderbouwing is optioneel en een hulp, geen eis. Bied het **één keer**
neutraal aan in plain tekst:

> *"Er hangt nog geen onderbouwing aan deze dag. Wil je er kort een
> toevoegen? Eén à twee zinnen over waar je aan werkte is genoeg.
> (Of zeg 'skip'.)"*

Geeft de gebruiker een beschrijving — kort of globaal — neem die
zoals 'ie is en POST naar `/evidence`. Toets niet, vraag niet door,
ga niet op zoek naar "het technische knelpunt".

Zegt 'ie "skip" / "later" / "nee" of geeft 'ie een heel dun antwoord:
respecteer dat, geen onderbouwing, klaar. Eén korte regel: *"Oké, dan
zonder onderbouwing."* Geen "RVO-risico bij jou", geen tegenvragen.
De boeking blijft staan.

### `over_8_hours`

Plain tekst: *"8+ uur is een rode vlag bij RVO-controle. Klopt
het echt dat je vandaag zoveel zuiver R&D-werk hebt gedaan, of
moeten we 't bijstellen?"*

### `weekend`

Plain tekst: *"Heb je echt op deze zaterdag/zondag gewerkt, of
moet de datum aangepast?"*

### Onderbouwing toevoegen

```bash
wbso evidence \
  --title "<titel ≤80>" \
  --description "<beschrijving>" \
  --date "<YYYY-MM-DD>"
```

`--external-id` is optioneel. Laat je 'm weg, dan gebruikt de skill een
vast id per dag (`wbso-onderbouwing-<user>-<datum>`), zodat een tweede
aanroep voor dezelfde dag de bestaande onderbouwing bijwerkt in plaats
van een duplicaat te maken. Wil je de onderbouwing aan één specifieke
boeking koppelen, geef dan `--external-id time_entry-<id>`.

### Onderbouwing verwijderen

Zelfde voorzichtigheid als bij uren: toon eerst kort wat weg gaat en
vraag bevestiging. Het `id` komt uit de JSON-respons van `wbso
evidence`.

```bash
wbso untrack-evidence --id <id>
```

## Verwijderen

Als de gebruiker uren wil verwijderen of een boeking wil annuleren:
**nooit direct deleten zonder bevestiging.** Verwijderen is
onomkeerbaar — geboekte uren met onderbouwing kunnen weg zijn voor
RVO-controle.

### Stap 1 — Toon eerst wat er weg gaat

Haal de relevante `time_entries` op (uit Stap 1 context, of GET op
specifieke datum). Toon ze als lijst met **alleen titel en uren**.
Geen IDs, slugs of andere interne details.

```
Wil je deze boekingen verwijderen?

- 4 uur op *Automatische git commit WBSO scoring agent*
- 1 uur op *Intake naar aanvraag conversie*

Totaal: 5 uur.
```

### Stap 2 — Bevestiging via keuzelijst

Verplicht. Geen vrije-tekst "ja" maar een keuzelijst als de client die
ondersteunt; anders vraag expliciet om één van deze antwoorden:

- *Ja, verwijder alles*
- *Alleen deze: <titel>* (één optie per boeking)
- *Annuleer*

Bij "Alleen deze": eventueel een tweede keuzelijst of expliciete
tekstvraag met sub-selectie als er meer dan twee zijn.

### Stap 3 — Verwijder en bevestig

Per geselecteerde boeking — gebruik intern de id, maar toon die niet:

```bash
wbso untrack-time --id <id>
```

Bevestig kort wat er is verwijderd, met titel en uren. Geen IDs en
geen HTTP-status codes naar de gebruiker:

```
Verwijderd:
- 4 uur op *Automatische git commit WBSO scoring agent*
- 1 uur op *Intake naar aanvraag conversie*

Vandaag staat nu nog 0 uur geboekt.
```

Bij API-fout (404/422 e.d.): vertaal naar mensentaal ("die boeking
bestaat niet meer", "het jaar is afgesloten — verwijderen kan niet").
Geen HTTP-codes oplezen.

## Platform feedback

Als je merkt dat de gebruiker vastzit, gefrustreerd raakt, een
vraag stelt over hoe het platform werkt, of expliciet iets zegt
over WBSO.ai (een bug, een wens, een compliment), bied dan **één
keer** aan om dat door te geven via de gebundelde `wbso-feedback` skill.
Volg die skill voor de daadwerkelijke flow.

Niet pushen, niet bij elk klein vraagje, niet ongevraagd op een
soepele flow. Eén korte plain-tekst-zin volstaat:

> *"Wil je dat ik dit doorgeef aan het WBSO.ai team als feedback?"*

Bij "ja": delegeer naar de `wbso-feedback` skill. Bij "nee" / "later":
respecteer dat en ga door.

## Notes

- API is idempotent op (user, project, date): tweede call op dezelfde
  dag overschrijft, geen duplicaat
- Reflog blijft **lokaal**; alleen uren + project + datum gaan naar de
  API. Geen git history of commit messages naar de server sturen.
- Config zit in `~/.config/wbso/config` (mode 600). Resetten: `rm
  ~/.config/wbso/config` en start deze skill opnieuw.

