Promote a scheme to user-authored on approve or edit (#99) #112

Merged
claude-bot merged 1 commit from fix/scheme-source-promotion into main 2026-09-04 16:28:19 +00:00
Contributor

Fixes #99.

What was wrong

Only community was promoted, which had two consequences:

An approved AI suggestion kept source: "ai" forever. Spec §3.3 layer 4 says it is "promoted to source 1" — it never was. The calendar's "AI-sourced" filter matches source === "ai", so a scheme the user had reviewed and adopted stayed in the review queue permanently and the filter never drained. That is the only thing the filter exists to do.

PUT /schemes/{id} never touched source at all, so a scheme whose colours, effect, speed and label had all been replaced still reported the template that contributed nothing to the result.

A third thing found while fixing it

The rule was duplicatedapprove_scheme and bulk_approve each spelled out the same if source == "community" check, so the bug existed in two places and any fix had to be made twice. It now lives in one _mark_user_authored helper used by approve, bulk approve and update.

The open question, decided

#99 left open whether approving an untouched builtin should promote. It does, for two reasons beyond the spec wording:

  • Spec §3.3 source 1 is "schemes the user has explicitly saved or approved" — which covers it on a plain reading.
  • scheme_generator.py:123 already marks a scheme carried forward from an approved prior occurrence as user. So leaving this year's approved copy as builtin while next year's regenerated copy said user contradicted the generator's own convention.

Recorded in spec §3.3 rather than left implicit in the code, since that was the actual failure here — the spec and the implementation disagreed and nothing said so.

Also

The edit audit entry now carries source in before/after, so the promotion shows up in the trail instead of being a silent side effect of an unrelated edit.

Verification

  • Backend: 301 passed (7 new), ruff, ruff format, mypy clean; all seven pre-commit hooks pass.
  • Approve is parametrised over builtin / fallback / community / ai.
  • One test asserts the specific behaviour that was broken: an ai scheme is in the AI-filtered set before approval and out of it after.
  • Two tests cover edits — segments and label — promoting the source.

No frontend change needed: SidePanel's source.includes("user") badge and the ai filter both start behaving correctly once the backend stops lying about provenance.

🤖 Generated with Claude Code

Fixes #99. ## What was wrong Only `community` was promoted, which had two consequences: **An approved AI suggestion kept `source: "ai"` forever.** Spec §3.3 layer 4 says it is *"promoted to source 1"* — it never was. The calendar's "AI-sourced" filter matches `source === "ai"`, so a scheme the user had reviewed and adopted stayed in the review queue permanently and the filter never drained. That is the only thing the filter exists to do. **`PUT /schemes/{id}` never touched `source` at all**, so a scheme whose colours, effect, speed and label had all been replaced still reported the template that contributed nothing to the result. ## A third thing found while fixing it The rule was **duplicated** — `approve_scheme` and `bulk_approve` each spelled out the same `if source == "community"` check, so the bug existed in two places and any fix had to be made twice. It now lives in one `_mark_user_authored` helper used by approve, bulk approve and update. ## The open question, decided #99 left open whether approving an untouched `builtin` should promote. It does, for two reasons beyond the spec wording: - Spec §3.3 source 1 is *"schemes the user has explicitly saved **or approved**"* — which covers it on a plain reading. - `scheme_generator.py:123` already marks a scheme **carried forward from an approved prior occurrence** as `user`. So leaving this year's approved copy as `builtin` while next year's regenerated copy said `user` contradicted the generator's own convention. Recorded in spec §3.3 rather than left implicit in the code, since that was the actual failure here — the spec and the implementation disagreed and nothing said so. ## Also The edit audit entry now carries `source` in `before`/`after`, so the promotion shows up in the trail instead of being a silent side effect of an unrelated edit. ## Verification - Backend: **301 passed** (7 new), `ruff`, `ruff format`, `mypy` clean; all seven pre-commit hooks pass. - Approve is parametrised over `builtin` / `fallback` / `community` / `ai`. - One test asserts the specific behaviour that was broken: an `ai` scheme is in the AI-filtered set before approval and out of it after. - Two tests cover edits — segments and label — promoting the source. No frontend change needed: `SidePanel`'s `source.includes("user")` badge and the `ai` filter both start behaving correctly once the backend stops lying about provenance. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Promote a scheme to user-authored on approve or edit (#99)
All checks were successful
CI / Pre-commit hooks (pull_request) Successful in 50s
CI / Alembic migration check (pull_request) Successful in 56s
CI / Python lint & type-check (pull_request) Successful in 1m0s
CI / Frontend lint, test & build (pull_request) Successful in 1m38s
CI / Python tests (pull_request) Successful in 2m12s
CI / Docker build, health smoke & E2E (pull_request) Successful in 1m50s
551f9e9ca9
Only `community` was promoted. Two consequences:

- Spec §3.3 layer 4 says an approved AI suggestion is "promoted to source 1".
  It never was, so it kept `source: "ai"` permanently. The calendar's
  "AI-sourced" filter matches on that, so a scheme the user had reviewed and
  adopted stayed in the review queue forever and the filter never drained --
  the only thing it exists to do.
- `PUT /schemes/{id}` never touched `source` at all, so a scheme whose
  colours, effect, speed and label had all been replaced still reported the
  template that contributed nothing to the result.

The promotion rule was also duplicated: `approve_scheme` and `bulk_approve`
each spelled out the same `if source == "community"` check, so any fix had to
be made twice. It now lives in one `_mark_user_authored` helper used by
approve, bulk approve, and update.

Approving promotes regardless of origin. Spec §3.3 source 1 is "schemes the
user has explicitly saved *or approved*", and `scheme_generator` already marks
a scheme carried forward from an approved prior occurrence as `user` -- so
leaving this year's approved copy as `builtin` while next year's said `user`
contradicted the generator's own convention. Recorded in the spec rather than
left implicit in the code.

The edit audit entry now includes `source` in before/after, so the promotion
is visible in the trail rather than being a silent side effect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
claude-bot deleted branch fix/scheme-source-promotion 2026-09-04 16:28:19 +00:00
Sign in to join this conversation.
No description provided.