Public: anyone can read this; the crew can change it.
A new issue's and pull's length limits live in one module, read by both forms #5605
Check · Review · Land · Live done — Landed and live in production.
The "too long" messages for a new issue's or pull's title and description now come from one new module, `src/actions/thread_limits_words.ts`. It exports `TITLE_TOO_LONG` ("That title is too long (256 characters at most).") and `BODY_TOO_LONG` ("That description is too long (64 KB at most)."). No module already held words like these, so it is new.
shipped production is serving it deploy 4915f35
The "too long" messages for a new issue's or pull's title and description now come from one new module, src/actions/thread_limits_words.ts. It exports TITLE_TOO_LONG ("That title is too long (256 characters at most).") and BODY_TOO_LONG ("That description is too long (64 KB at most)."). No module already held words like these, so it is new.
- Issue form:
src/web/pages/issues.tsimports both constants and uses them in place of the typed sentences when an issue fails to open. - Pull form:
src/web/pages/pulls.tsuses them for thetitle_too_longandbody_too_longentries inCOMPOSE_ERRORS.
Only the import line and the sentence lines changed in each file, and no wording changed. grep -rn for each full sentence under src/ now finds only the new module.
Left alone on purpose: two similar messages aren't in the issue's list, so they stay where they are:
thread.tssays "That description is too long." with no limit in it.reports.tsbuilds its title message fromTITLE_MAXand adds "The report is still waiting."
Test: the new test/thread-limits-words.test.ts checks that each exported sentence is a non-empty string. It also reads both page files as text and fails if they stop importing the module or if either sentence is typed back in.
Checks run, all passing: the new test, bun x tsc --noEmit, bun scripts/design-lint.ts, and test/issues.test.ts, test/pulls.test.ts, test/new-pull-timing.test.ts, test/issue-timing.test.ts and test/edit-words.test.ts. No existing test was changed.
To try it, open a new issue or pull with a title over 256 characters: the form comes back with the same sentence as before.
🤖 Generated with Claude Code
Does what the issue asked: one module holds the two sentences, both forms import them, wording is unchanged, no new dependency, no markup or CSS touched, so the design system and JS-off behaviour are unaffected. Two things I would do next: (1) build the sentences from MAX_TITLE and MAX_BODY in src/core/issues.ts instead of typing 256 and 64 KB, so the numbers cannot drift from the real limits; (2) add a behavioural test that posts an over-long title to the new issue and new pull forms and asserts the sentence, since the current test only greps source text. The terminal screens in src/tui/screens/common.ts:832 keep their own lowercase wording; fine as is, but worth a follow-up if the two doors should share words.
The length limits for a new issue and a new pull now live in one module, src/actions/thread_limits_words.ts, which exports TITLE_TOO_LONG and BODY_TOO_LONG. Both src/web/pages/issues.ts and src/web/pages/pulls.ts read their messages from it instead of each keeping its own copy, so the two forms can't drift apart. test/thread-limits-words.test.ts covers it, and behaviour is unchanged.
This branch now has main merged in. The one conflict was the import block of src/web/pages/issues.ts: main had added an import of COMMENT_EMPTY and COMMENT_NOT_POSTED from comment_words.ts, and this branch had added the thread_limits_words.ts import. Both are kept, because the page uses all four. After the merge the type check is clean, the limits and issue/comment tests pass (78 of 78), and the design lint is clean.
To try it, open "new issue" or "new pull" on any repository and submit a title or body over the limit: both forms show the same message.
🤖 Generated with Claude Code
Approved. The two forms now read one module, wording is unchanged, the diff is small and single-purpose, and the preview answers 200. No new markup, so the design system is untouched. Next, in order: (1) the terminal door has its own lowercase copies of the same limits in src/tui/screens/common.ts (title_too_long, body_too_long), so the three doors can still drift; decide whether to share the numbers or keep the terminal voice on purpose. (2) The test greps source text for the sentences. A behavioural test would be sturdier: submit an over-length title to both forms and assert the shared sentence appears in the response.
The "too long" messages for a new issue's or pull's title and description now come from one new module,
src/actions/thread_limits_words.ts. It exportsTITLE_TOO_LONG("That title is too long (256 characters at most).") andBODY_TOO_LONG("That description is too long (64 KB at most)."). No module already held words like these, so it is new.src/web/pages/issues.tsimports both constants and uses them in place of the typed sentences when an issue fails to open.src/web/pages/pulls.tsuses them for thetitle_too_longandbody_too_longentries inCOMPOSE_ERRORS.Only the import line and the sentence lines changed in each file, and no wording changed.
grep -rnfor each full sentence undersrc/now finds only the new module.Left alone on purpose: two similar messages aren't in the issue's list, so they stay where they are:
thread.tssays "That description is too long." with no limit in it.reports.tsbuilds its title message fromTITLE_MAXand adds "The report is still waiting."Test: the new
test/thread-limits-words.test.tschecks that each exported sentence is a non-empty string. It also reads both page files as text and fails if they stop importing the module or if either sentence is typed back in.Checks run, all passing: the new test,
bun x tsc --noEmit,bun scripts/design-lint.ts, andtest/issues.test.ts,test/pulls.test.ts,test/new-pull-timing.test.ts,test/issue-timing.test.tsandtest/edit-words.test.ts. No existing test was changed.To try it, open a new issue or pull with a title over 256 characters: the form comes back with the same sentence as before.
🤖 Generated with Claude Code
Closes #5587