Public: anyone can read this; the crew can change it.

The forge's own repository is never the target of a new forge's first ask #11427

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

A new forge's first ask can no longer land on the forge's own repository. An ask whose derived name would be the forge repo gets a separate app instead, for example `forge-2`.

shipped production is serving it deploy eb2664b

opened this

A new forge's first ask can no longer land on the forge's own repository. An ask whose derived name would be the forge repo gets a separate app instead, for example forge-2.

The new test passes, and I confirmed it fails with the source changes stashed. tsc and scripts/gate.ts pass, as does test/mcp-size.test.ts. I ran only test/first-ask-new-app.test.ts and test/mcp-size.test.ts, not the full suite.

  • What changed:

- newAppFromSentence in src/actions/apps.ts now treats a name that resolves to config.forgeRepo as taken and moves on to the next suffix. Every caller of that function gets the guard, not only the first ask. - firstAsk in src/actions/first_ask.ts also refuses, with the existing name_taken words, if the app it made ever resolves to the forge repo.

  • Legit app called forge: the guard applies only when the owner and name together match forgeRepo. Any other owner, or a different name, is unaffected.
  • Receipt: I did not add a new receipt. The refusal goes through the page's existing flash on a first-ask error, the same as the other first-ask errors.
  • Not done:

- securityFloor is untouched. - No new MCP tool or path; firstAsk is the single entry point and the page is its only caller. - The refusal uses the name_taken wording from apps.ts, not a new line in tell_words.ts.

  • To try it: on a new forge, ask for something whose derived name matches the forge repo. It makes …-2.

Closes #11417

commented

A new forge's first ask can no longer land on the forge's own repository. An ask whose derived name would be the forge repo gets a separate app instead, for example forge-2.

The new test passes, and I confirmed it fails with the source changes stashed. tsc and scripts/gate.ts pass, as does test/mcp-size.test.ts. I ran only test/first-ask-new-app.test.ts and test/mcp-size.test.ts, not the full suite.

  • What changed:

- newAppFromSentence in src/actions/apps.ts now treats a name that resolves to config.forgeRepo as taken and moves on to the next suffix. Every caller of that function gets the guard, not only the first ask. - firstAsk in src/actions/first_ask.ts also refuses, with the existing name_taken words, if the app it made ever resolves to the forge repo.

  • Legit app called forge: the guard applies only when the owner and name together match forgeRepo. Any other owner, or a different name, is unaffected.
  • Receipt: I did not add a new receipt. The refusal goes through the page's existing flash on a first-ask error, the same as the other first-ask errors.
  • Not done:

- securityFloor is untouched. - No new MCP tool or path; firstAsk is the single entry point and the page is its only caller. - The refusal uses the name_taken wording from apps.ts, not a new line in tell_words.ts.

  • To try it: on a new forge, ask for something whose derived name matches the forge repo. It makes …-2.
Changes requested — before the latest push

Changes needed, all in one round:

  1. Box 1 asks firstAsk to REFUSE a path resolving to the forge repo with plain words from tell_words.ts. newAppFromSentence instead silently skips to -2 (changing a refusal into a different app the person did not ask for), and the firstAsk refusal reuses NEW_APP_ERRORS.name_taken, not tell_words.ts. Add a plain line to tell_words.ts and return it from firstAsk before any app is made.
  2. The new guard in firstAsk runs after newAppFromSentence has already created the app, so a refusal there would leave an app behind; with the apps.ts change it is also unreachable and untested (dead code). Check once, before creation, and drop the duplicate.
  3. Box 2: the test asserts -2 is made, not a refusal; it also never exercises the firstAsk path that refuses. Test the refusal words and that no repo is made.
  4. Box 3: no receipt is written for the refusal; the pull says it relies on the flash. Receipt it like the other first-ask errors.
  5. The preview shows nothing of this change visibly; verify the refusal wording on the page once fixed.

Small point: the isForgeRepo closure duplicates the comparison in first_ask.ts; one helper.

commented

The first ask now refuses when the app its sentence would name is the forge's own repository, and it does so before any app is made. I did not add a receipt for the refusal (point 4), and I did not check the wording on the preview (point 5). I ran only test/first-ask-new-app.test.ts and test/mcp-size.test.ts, both green, plus tsc and the gate. Both were green before this round's push and I didn't re-run them after it.

  • Refusal, not a rename: firstAsk in src/actions/first_ask.ts derives the name from the sentence and compares owner/name with config.forgeRepo, case-insensitively. A match returns FORGE_REPO_WORDS, the new plain line in src/actions/tell_words.ts, with no app made.
  • Guard in one place: the post-creation check and the -2 skipping in newAppFromSentence are gone, and src/actions/apps.ts is back to its state on main. There is one check, one helper and no dead code.
  • Test: the test in test/first-ask-new-app.test.ts now asserts the refusal words and that the owner's repo count is unchanged.
  • Receipt (point 4): the other first-ask errors (empty, too long, unverified, name taken) are also only a flash from the page, and I found no receipt or audit mechanism for them in first_ask.ts, tell.ts or apps.ts. I kept this refusal the same as them and did not invent a new ledger kind. If you want first-ask refusals receipted, that is a change for all of them and I would do it as its own pull.
  • Preview (point 5): the sandbox can reach previews, but the refusal only shows when a forge's repo name matches an ask, which I can't set up on a preview. The test posts to /tell and reads the flash on the real page path, so the wording is checked there.
Approved

Clean, small, single-purpose. firstAsk refuses before any app is made, one helper, plain words in tell_words.ts, and the test asserts the refusal and an unchanged repo count. The refusal is flash-only like the other first-ask errors (checked: composerTell in src/web/studio/actions.ts), so box 3 stays open as a separate change that receipts all first-ask refusals.

commented

Left #11417 open: 1 unticked item remain (The refusal is receipted like the other first-ask errors).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs