Public: anyone can read this; the crew can change it.
A label's shape refusal lives in one module, and the settings page and MCP read it from there #5581
Check · Review · Land · Live done — Landed and live in production.
The sentence "A label needs a name and a six-digit hex color." now lives only in the new `src/actions/label_words.ts`, as `LABEL_WORDS.shape`. The settings page and MCP `repo_labels` both import it from there, so it can't drift between them.
shipped production is serving it deploy 5f89d5b
The sentence "A label needs a name and a six-digit hex color." now lives only in the new src/actions/label_words.ts, as LABEL_WORDS.shape. The settings page and MCP repo_labels both import it from there, so it can't drift between them.
What moved: the settings page typed the sentence out twice, once in labelCreate and once in labelUpdate, and src/http/mcp.ts (repo_labels, create action) typed it once. Each of those lines now reads LABEL_WORDS.shape, and each door gains one import line. No other line changed, as the issue asked, since other MCP work is editing mcp.ts at the same time. The wording is unchanged.
How the new test covers each door: test/label-words.test.ts covers the settings page by posting a label whose name is only spaces. It follows the redirect and checks that the page shows the module's sentence. MCP can't be covered the same way: repo_labels checks the name and colour itself before calling createLabel, so its "invalid" branch can't be reached from outside. The test instead checks that mcp.ts imports the module and uses LABEL_WORDS.shape. A third test walks every .ts file under src/ and fails if any file except label_words.ts contains the sentence, so retyping it in either door turns the suite red.
Checks: test/label-words.test.ts, test/settings.test.ts, test/mcp-repo-labels.test.ts and test/mcp.test.ts pass (53 tests), none of the existing tests were edited, and bun x tsc --noEmit is clean.
Not done: the other label refusals ("already has a label by that name", "That label no longer exists.") are still typed out in each door, because the issue named only this sentence.
🤖 Generated with Claude Code
Clean, pure move, and it does what #5566 asked. The sentence now lives only in src/actions/label_words.ts. Each door changes the literal's own line plus one import, which keeps the parallel MCP edits safe. Security: no auth, input or output path changes. The admin-scope check in repo_labels and the settings write guards are untouched. The preview at this head answers /, and an anonymous POST to a settings/labels route is still refused (404). Design: the only edit under src/web/ swaps a string for a constant, with no markup, so docs/DESIGN.md is unaffected. Tests: the settings door is exercised end-to-end through the flash. The MCP invalid branch can't be reached because repo_labels validates name and colour first. That makes the source assertion plus the whole-src/ sweep a fair way to hold it, and the sweep fails if either door retypes the words. A follow-up worth filing separately: MCP's own pre-checks ("name is one to 64 characters", "color is six hex digits") already word the shape refusal differently from the page, so the doors don't fully read the same yet.
The sentence "A label needs a name and a six-digit hex color." now lives only in the new
src/actions/label_words.ts, asLABEL_WORDS.shape. The settings page and MCPrepo_labelsboth import it from there, so it can't drift between them.What moved: the settings page typed the sentence out twice, once in
labelCreateand once inlabelUpdate, andsrc/http/mcp.ts(repo_labels, create action) typed it once. Each of those lines now readsLABEL_WORDS.shape, and each door gains one import line. No other line changed, as the issue asked, since other MCP work is editingmcp.tsat the same time. The wording is unchanged.How the new test covers each door:
test/label-words.test.tscovers the settings page by posting a label whose name is only spaces. It follows the redirect and checks that the page shows the module's sentence. MCP can't be covered the same way:repo_labelschecks the name and colour itself before callingcreateLabel, so its"invalid"branch can't be reached from outside. The test instead checks thatmcp.tsimports the module and usesLABEL_WORDS.shape. A third test walks every.tsfile undersrc/and fails if any file exceptlabel_words.tscontains the sentence, so retyping it in either door turns the suite red.Checks:
test/label-words.test.ts,test/settings.test.ts,test/mcp-repo-labels.test.tsandtest/mcp.test.tspass (53 tests), none of the existing tests were edited, andbun x tsc --noEmitis clean.Not done: the other label refusals ("already has a label by that name", "That label no longer exists.") are still typed out in each door, because the issue named only this sentence.
🤖 Generated with Claude Code
Closes #5566