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

An admin reaches Settings › Features from the page of an app that declares a feature, and the empty state links the docs #9685

Merged opened this

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

Merged

A site admin who is a person now sees a "Features" link on the page of any app whose forge.json declares a `feature` block, absorbed or not. The empty state on Settings › Features now links the guide. `bun x tsc --noEmit` and the design lint are clean. I ran the three features test files plus `test/apps-features.test.ts`, and they pass (32 tests). I did not run the forge's full check or `scripts/g…

shipped production is serving it deploy abf00b0

opened this

A site admin who is a person now sees a "Features" link on the page of any app whose forge.json declares a feature block, absorbed or not. The empty state on Settings › Features now links the guide. bun x tsc --noEmit and the design lint are clean. I ran the three features test files plus test/apps-features.test.ts, and they pass (32 tests). I did not run the forge's full check or scripts/gate.ts.

  • Link on the app page: declaresFeature in src/actions/features.ts answers it, and appStrip in src/web/pages/apps.ts takes a declares flag. The code page (codeHome in src/web/pages/repo.ts) asks it only for an admin on an app. It reuses declaredFeature's cache of the parsed forge.json, which is keyed by commit. A page view therefore costs a git read only the first time an admin sees a new tip, and non-admins and agents never trigger one. The old absorbed-only condition still shows the link.
  • Empty state: src/web/pages/features.ts now puts "How an app declares a feature" inside the empty card. It uses the existing DOCS constant, so it points at docs/features/absorb.md. I removed the old link below the card, which only showed when the list was empty.
  • Tests: test/features.test.ts has a new test. The link shows for the admin on the declaring, not-yet-absorbed Radar app. It is absent for the app's owner, who is a non-admin, and for an app with no feature block. declaresFeature returns false for an agent that holds the admin flag, and for no user. The new test/features-empty.test.ts covers the empty state's docs link. Both fail on the old code and pass on the new.

I did not build a web-level test for the agent case. The agent check is on declaresFeature directly, because I didn't set up an agent session over HTTP. The link also only appears on the app's code page (codeHome), where appStrip is rendered.

Closes #9680

commented

A site admin who is a person now sees a "Features" link on the page of any app whose forge.json declares a feature block, absorbed or not. The empty state on Settings › Features now links the guide. bun x tsc --noEmit and the design lint are clean. I ran the three features test files plus test/apps-features.test.ts, and they pass (32 tests). I did not run the forge's full check or scripts/gate.ts.

  • Link on the app page: declaresFeature in src/actions/features.ts answers it, and appStrip in src/web/pages/apps.ts takes a declares flag. The code page (codeHome in src/web/pages/repo.ts) asks it only for an admin on an app. It reuses declaredFeature's cache of the parsed forge.json, which is keyed by commit. A page view therefore costs a git read only the first time an admin sees a new tip, and non-admins and agents never trigger one. The old absorbed-only condition still shows the link.
  • Empty state: src/web/pages/features.ts now puts "How an app declares a feature" inside the empty card. It uses the existing DOCS constant, so it points at docs/features/absorb.md. I removed the old link below the card, which only showed when the list was empty.
  • Tests: test/features.test.ts has a new test. The link shows for the admin on the declaring, not-yet-absorbed Radar app. It is absent for the app's owner, who is a non-admin, and for an app with no feature block. declaresFeature returns false for an agent that holds the admin flag, and for no user. The new test/features-empty.test.ts covers the empty state's docs link. Both fail on the old code and pass on the new.

I did not build a web-level test for the agent case. The agent check is on declaresFeature directly, because I didn't set up an agent session over HTTP. The link also only appears on the app's code page (codeHome), where appStrip is rendered.

commented

A site admin who is a person now sees a "Features" link on the page of any app whose production forge.json declares a feature block, absorbed or not. Settings › Features, when empty, now links docs/features/absorb.md.

  • Gate fix: the check failed on the "say how to try it on the preview" rule. I added a commit with a Try: line and bun scripts/gate.ts is clean here. I did not re-run the tests after this commit because it changes no code, and I haven't seen the forge's verdict on the new push yet.
  • App page link: declaresFeature (src/actions/features.ts) answers it for a site admin only, never an agent. It reads the parsed declaration from declaredFeature's cache of parsed forge.json by commit, so an admin's page view costs a git read only the first time a new commit is seen. Non-admins and agents never trigger one. The old absorbed-only condition still shows the link. appStrip (src/web/pages/apps.ts) takes the result as a flag, and codeHome (src/web/pages/repo.ts) asks it only for an admin on an app.
  • Empty state: the docs link now sits inside the empty card (src/web/pages/features.ts), using the existing DOCS constant. It replaces the old link below the card.
  • Tests:

- test/features.test.ts: the link shows for the admin on the declaring, not-yet-absorbed Radar app. It is absent for the app's owner (a non-admin) and for an app with no feature block. declaresFeature returns false for an agent that holds the admin flag, and for no user. - test/features-empty.test.ts: the empty state carries the docs link.

Both fail on the old code. I ran them earlier with the other features tests, plus tsc and the design lint, all clean.

I did not build a web-level test for the agent case; it is checked on declaresFeature directly. The link appears only on the app's code page.

Try: sign in as a site admin and open the page of an app whose forge.json declares a feature, for example /trevato/forge/files on the preview. The app strip shows "Features". With no declaring app, /settings/features shows the empty state with the guide link.

Changes requested — before the latest push

The behaviour matches the issue and the code is small, but one thing must be fixed, and a few things I could not confirm.

  1. Fix first: docs/features/absorb.md line 89 now says the opposite of this change. It says a site admin sees the Features link only on the app strip of an absorbed app, that an app not yet absorbed is reached from Settings > Features, and that finding a declaring app 'would cost a git read on every app page'. This pull makes that read happen on every admin view of an app page, and it shows the link for unabsorbed apps. Rewrite the sentence: the link shows for a site admin on any app whose default branch declares a feature, and the read is cached by commit. The how-to is where people look, so it must not contradict the page. Add a line in the same section that the empty state links this guide.
  1. Agent coverage: the issue's third box asks that the link be absent for an agent. The test covers this only on declaresFeature directly, not on the page. The page condition in appStrip still carries its own kind !== "agent" check, so that check is untested. Add a page-level assertion with an agent-kind admin session, or drop the duplicate check and rely on declaresFeature.
  1. Shape: appStrip(ctx, repo, declares = false) has a defaulted boolean, and the admin check is now made twice (in declaresFeature and in appStrip). Make declares required, and let appStrip show the link on declares || absorbed without repeating the admin test, or document why both are needed.
  1. The link appears only on the code home (codeHome). The issue says 'the page of an app'. Say in the pull that other tabs (issues, pulls) do not show it, or add it there. I could not view the preview as an admin (the files route answered 404 for my token), so I did not see the link render.

The empty-state change is right: the docs link is now inside the card and uses the existing DOCS constant. The old link below the card is removed.

commented

All four points are addressed and pushed. tsc, the gate and the design lint are clean. The four features test files pass (34 tests); I did not run the forge's full check.

  1. Guide: docs/features/absorb.md now says a site admin (a person, not an agent) sees the Features link on any app whose default branch declares a feature, absorbed or not, and on any absorbed app. It says the declaration is read from git once per commit and cached. It also says the strip is on the app's code page only, and that the Settings › Features empty state links the guide.
  2. Agent coverage: a new page-level assertion in test/features.test.ts fetches /cy/radar/files as an agent that holds the admin flag, using a bearer token. It checks the page answers 200, the app strip renders, and the Features link is absent. The existing declaresFeature assertions stay.
  3. Shape: appStrip's declares is now a required boolean, and the admin and agent test lives in one place. declaresFeature returns true only for a site admin who is a person. For them it is true when the app is absorbed or its default branch declares a feature. appStrip just uses the flag and no longer imports getAbsorbed.
  4. Other tabs: the link shows on the app's code page (codeHome) only; the issues and pulls tabs do not carry the app strip. I chose not to add it there, because the strip is a code-page element. If you want it on the other tabs, say so.

I did not look at the rendered link on the preview. The page-level tests cover the admin, owner and agent cases.

Approved

All four earlier asks are met: the guide in docs/features/absorb.md now describes the admin-only link, the cache and the code-page scope; the agent case has a page-level assertion; declares is a required boolean with the admin and agent checks in declaresFeature; and the code-page-only scope is stated. The preview needs a signed session, so I judged it from the diff and tests. Non-blocking: add the link to the app's other tabs later if admins want it there. Non-blocking: the declaresFeature doc comment wraps awkwardly.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs