Comments, docstrings and a few strings cited plan numbers ("plan 29
#9", "plan 86 §B2") from a git-ignored folder, so they pointed at
nothing; one reached users in a bottleneck hint. Code and frontend
strings are unchanged apart from those citations (checked by AST and
token comparison). A vhost still carrying the old asset comment reads
as undrifted, and a guard test keeps new citations out.
Applies the panel copy rules to the five builtin extensions. Tab,
page-title and command-palette labels go to sentence case (Cloud
servers, FTP server, Remote access, Status pages); display names stay
as extension names.
Walkthrough Studio: no period on short toasts, "Couldn't" errors, a
delete confirm that states the consequence, and four hardcoded strings
wrapped in t() (kicker, step eyebrow, default duration and action),
with Spanish for the new keys. 30 strings in all: Studio 16, cloud
provisioning 4, FTP 4, remote access 3, status 3.
Synced into frontend/src/plugins and the tracked live serverkit-status
manifest.
PR #122 review. Four routes passed request.get_json() straight into the
service, which does `if field in data` and raises TypeError on None.
Copilot reported the trigger as "empty/invalid JSON bodies"; measured on
Flask 3.1.3 that is wrong — an empty body is already a 400 and a wrong
content-type a 415, both raised by Flask before the view runs. The body
that actually reaches the view is literal `null`, which is valid JSON and
decodes to None. Same fix, accurate reason.
Also corrects plugin.json, which claimed installing the extension serves
the public /status/<slug> pages; the registry catalog says that page
stays core, and the two contradicted each other.
Both copies edited — app/plugins/ is the live copy the loader imports,
builtin-extensions/ is the source — and a test pins that they agree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
serverkit-email's live copy under app/plugins/ was the only git-TRACKED
one, which is what kept test_builtin_extension_drift non-vacuous on a
fresh clone. Plan 52's cutover deletes it, so on CI the guard had zero
pairs to compare and test_drift_check_is_not_vacuous fired -- correctly.
It still passed on a dev box, where the gitignored live copies exist, so
the failure only reproduces in a clean checkout.
Track serverkit-status's live copy instead (verified byte-identical to
builtin-extensions/serverkit-status/backend), un-ignore just that path,
and update both docstrings to name the new anchor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>