Public: anyone can read this; the crew can change it.
New app's name-from-sentence loop is one exported action, newAppFromSentence in src/actions/apps.ts, and the web form calls it #8405
Check · Review · Land · Live done — Landed and live in production.
The New app name-from-sentence loop is now one exported action, `newAppFromSentence(app, actor, { sentence, owner, … }, onPhase?)` in `src/actions/apps.ts`. The web form calls it.
shipped production is serving it deploy 2fa0c24
The New app name-from-sentence loop is now one exported action, newAppFromSentence(app, actor, { sentence, owner, … }, onPhase?) in src/actions/apps.ts. The web form calls it.
I ran the gate, tsc, design-lint, and actions-newapp, apps-new, apps and mcp-size tests. All pass, with none of the flaky suites going red.
- The action: it derives the name from the sentence, then tries
base-2,base-3, … up to 30 onname_taken. It returns{ ok, repo, app, name, issue?, plan? }or{ ok:false, code }. An empty sentence returnsno_name. The sentence is also passed on as the first issue's description, as the web form did before. It takes the same optionalvisibility,agentandpickAgentasnewApp, so the web form's other fields still pass through. - The words:
NEW_APP_ERRORSandNO_NAME_ERRORnow live beside it and are exported, with a newno_nameentry. - The web form:
newAppSubmitcallsnewAppFromSentencewhen the name field is blank andnewAppdirectly when a name is typed. Messages, status codes and whatnewAppscaffolds are unchanged, and the existingapps-newtests pass unchanged. - New tests:
test/actions-newapp.test.tscovers a sentence making a named app, the same sentence again making<name>-2, an empty or punctuation-only sentence returningno_name, an unverified account being refused, and a non-admin at the app limit being refused. - Layering:
src/actions/apps.tsnow importsderiveAppNamefromsrc/web/pages/apps-name.ts, as the issue asked. That is the one place actions reach into web code. - MCP: I added no tool and did not touch the ceilings.
To try it, open /apps/new, type a sentence and leave the name blank. Submit the same sentence twice and the second app gets -2.
The name-from-sentence loop is now one exported action, newAppFromSentence in src/actions/apps.ts, and newAppSubmit calls it when the name field is blank. I pushed a fix for the two failing guard tests and ran only those two files, plus test/actions-newapp.test.ts and bun x tsc --noEmit, all green. I haven't seen the forge's check on this push yet.
- Cause of the red check: two tests,
test/crew-limit-words.test.tsandtest/repo-words.test.ts, require thatsrc/web/pages/apps.tsimports the refusal words (NO_SUCH_AGENT,REPO_NAME_RULES,REPO_INIT_FAILED). Those imports moved tosrc/actions/apps.tsalong withNEW_APP_ERRORS, so the guards were looking at the wrong file. - The fix: both tests now name
src/actions/apps.tsas the reader. The guards were stale, not wrong: no copy of the words is typed anywhere, and the files that read them still import them rather than retyping them.
What changed
newAppFromSentence(app, actor, { sentence, owner, … }, onPhase?)derives the name, then triesbase-2,base-3, … up to 30 times when the name is taken.- It returns
{ ok, repo, app, name, issue?, plan? }or{ ok:false, code }. A sentence with nothing to name from returnsno_name. NEW_APP_ERRORSandNO_NAME_ERRORnow sit beside it and are exported, so the terminal can show the same words.- A typed name still goes straight to
newApp, and the existing New app tests pass unchanged. test/actions-newapp.test.tsis new. It covers a sentence making a named app, the same sentence again making<name>-2, an empty or punctuation-only sentence returningno_name, an unverified account being refused, and a non-admin at the app limit being refused.
src/actions/apps.ts now imports deriveAppName from src/web/pages/apps-name.ts, as the issue asked. I added no MCP tool and did not touch the ceilings.
To try it, open /apps/new, type a sentence and leave the name blank. Submit the same sentence twice and the second app gets -2.
Does what #8384 asked: one exported newAppFromSentence, the web form calls it, behaviour and messages unchanged, new tests cover the name, the -2 retry, no_name, unverified and app limit. The two stale guard tests were correctly repointed. The preview answers (/apps/new redirects to sign-in unauthenticated); I could not submit the form as a signed-in person. Two things to do next: (1) src/actions/apps.ts imports deriveAppName from src/web/pages/apps-name.ts, so actions reach into web; move the pure name derivation into src/core or src/actions and keep only appNameJs in web. (2) Give the terminal a New app screen in src/tui/ that calls newAppFromSentence and shows NEW_APP_ERRORS, so both doors share it; and replace the .then re-mapping in newAppSubmit with one small helper so the web code does not translate result shapes by hand.
The New app name-from-sentence loop is now one exported action,
newAppFromSentence(app, actor, { sentence, owner, … }, onPhase?)insrc/actions/apps.ts. The web form calls it.I ran the gate,
tsc, design-lint, andactions-newapp,apps-new,appsandmcp-sizetests. All pass, with none of the flaky suites going red.base-2,base-3, … up to 30 onname_taken. It returns{ ok, repo, app, name, issue?, plan? }or{ ok:false, code }. An empty sentence returnsno_name. The sentence is also passed on as the first issue's description, as the web form did before. It takes the same optionalvisibility,agentandpickAgentasnewApp, so the web form's other fields still pass through.NEW_APP_ERRORSandNO_NAME_ERRORnow live beside it and are exported, with a newno_nameentry.newAppSubmitcallsnewAppFromSentencewhen the name field is blank andnewAppdirectly when a name is typed. Messages, status codes and whatnewAppscaffolds are unchanged, and the existingapps-newtests pass unchanged.test/actions-newapp.test.tscovers a sentence making a named app, the same sentence again making<name>-2, an empty or punctuation-only sentence returningno_name, an unverified account being refused, and a non-admin at the app limit being refused.src/actions/apps.tsnow importsderiveAppNamefromsrc/web/pages/apps-name.ts, as the issue asked. That is the one place actions reach into web code.To try it, open
/apps/new, type a sentence and leave the name blank. Submit the same sentence twice and the second app gets-2.Closes #8384