Skip to content

Give the buddy a map of the app: get_app_guide - #301

Merged
DavidLeuter merged 7 commits into
devfrom
feature/buddy-page-knowledge
Oct 4, 2026
Merged

DavidLeuter merged 7 commits into
devfrom
feature/buddy-page-knowledge

Conversation

@DavidLeuter

@DavidLeuter DavidLeuter commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

Short summary

Frontend half of the buddy's app guide (get_app_guide in the backend): the buddy learns which page the user is on, and the app guide's coverage is guarded from this repo.

  • currentPage: every buddy message sends window.location.pathname, so "what can I do here?" is answered for the page the dock floats over. Read at send time, not via useLocation, so navigation doesn't re-render the conversation.
  • Tool label "Checking where that is in the app…" for get_app_guide.
  • Coverage tripwire: accessPolicy.ts exports APP_ROUTES; features/buddy/appGuideRoutes.ts lists the routes the backend's AppGuide.kt describes plus deliberate exclusions, and appGuideRoutes.test.ts fails when a new route is in neither.
  • Fix in AdminPage: ?tab= is now followed while the page is already open. Before, a buddy link like /admin?tab=projects clicked on /admin kept the current tab and left the parameter in the URL. Respects the admin-only Skills tab (visibleAdminTabs).
  • Docs: the rule to update the guide lives in docs/FRONTEND_ARCHITECTURE.md §4.3, with a pointer in AGENTS.md.

Checks

  • I verified the code makes sense intuitively
  • The PR changes affect only this issue, no unrelated/unwanted code changes to other modules/code segments
  • CI runs (npm ci, npm run lint, npm run build)
  • New logic is unit tested (Vitest), including a11y tests for changed pages/components
  • The new functionality is tested manually

Additional notes

Part of a three-repo change; each PR works on its own, but the feature needs all three:

dev is merged in as of today. Not yet tried end to end with a real model.

🤖 Generated with Claude Code

DavidLeuter and others added 5 commits September 30, 2026 15:22
The backend's new get_app_guide tool answers "where do I…" questions
about the app itself. Two things make its answers usable here:

- streamMessage sends the pathname the dock is floating over as
  currentPage, so "what can I do on this page?" has a "this page".
- Root-relative links in a buddy reply navigate in place instead of
  reloading the app in a new tab (same change as on the 311 branch, so
  the two merge cleanly).

Plus a status label for the tool while it runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The buddy's map of the app (get_app_guide) lives in the backend's
AppGuide.kt. appGuideRoutes.ts mirrors its route list, and a test fails
when accessPolicy.ts has a route that is neither described there nor
excluded on purpose — so a new page trips CI in the repo it was added in.
accessPolicy.ts exports APP_ROUTES for it; AGENTS.md says to keep the
guide in step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The buddy links to /admin?tab=projects in place. The tab parameter was only
read on mount, so somebody already on the page kept their tab while the
parameter sat in the URL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…wledge

# Conflicts:
#	AGENTS.md
#	src/auth/accessPolicy.ts
#	src/pages/AdminPage.tsx
…wledge

# Conflicts:
#	src/pages/AdminPage.tsx
#	tests/unit/pages/AdminPage.test.tsx
@DavidLeuter
DavidLeuter requested review from BabuPlk, daniilperkin and kiranfin and removed request for BabuPlk and daniilperkin October 3, 2026 16:31

@kiranfin kiranfin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

The change is small and well scoped: currentPage is read at send time rather than through useLocation, APP_ROUTES replaces the duplicated Object.keys(...), and the omit-if-absent request body is covered by a service test. I also checked the parts that live in the other repo. APP_GUIDE_ROUTES mirrors the page order of AppGuide.kt, and the tab/view labels the guide quotes exist in the frontend. The deep links the guide emits (/team-management?tab=roles, /hire-setup?tab=arrival|starter, /insights/knowledge-requests?view=answered) already derive their state live from the URL, so AdminPage was indeed the only page that needed to follow ?tab= in place. I ran appGuideRoutes, buddyService and AdminPage tests against the branch and they pass. The remaining concerns are a UI inconsistency in the new tab-follow path and a blind spot in the new coverage tripwire.

🟡 Worth a look

  1. A ?tab= link followed while the page is open bypasses handleTabChange, so an open drawer stays on top of the new tab — src/pages/AdminPage.tsx:111-120, src/pages/AdminPage.tsx:699-707
    The render-phase adjustment calls setActiveTab(requestedTab) directly. Every user-driven switch goes through handleTabChange, which first clears openUserMenuId and closes an open drawer (closeDetails()). The drawers are rendered from selectedUser / selectedProject / selectedSkill, independent of activeTab. The buddy dock is non-modal, so this is reachable: open a user on Users, then click a buddy link to /admin?tab=projects. The tab changes underneath, but the user drawer (and its backdrop) stays open over Projects. I reproduced this with a throwaway test: after the tab followed, "John Details" was still rendered. closeDetails schedules a timeout, so it cannot simply be called from the render-phase block; handle the close in the effect (or route the URL-driven change through the same function as handleTabChange) and add a regression test with a drawer open.

  2. The coverage tripwire cannot see routes that are not in routePermissions — src/features/buddy/appGuideRoutes.ts:80-105, src/router/AppRouter.tsx
    appGuideRoutes.test.ts compares the guide against APP_ROUTES, i.e. Object.keys(routePermissions). AppRouter also registers /skill-wizard, which has no routePermissions entry. A new page added the same way would pass CI with no decision about the guide, which is exactly what the PR title ("Fail CI when a page is added without a decision") promises to prevent. /skill-wizard is currently the example the backend tests use for "a page this guide does not describe", so nothing records that decision on this side. APP_GUIDE_EXCLUDED_ROUTES is typed Partial<Record<AppRoute, string>>, so it cannot hold such a route either. Either widen the check to the router's actual paths or state the limitation in the test and in FRONTEND_ARCHITECTURE.md §4.3 (which currently reads as full coverage).

🟢 Nits / cleanup

  • The new test only covers Users → Projects with no drawer open. Missing cases: a drawer open while the link arrives (finding 1), the same link followed twice (the render-phase comment says this is why handledTab exists), and ?tab=skills followed by a non-ADMIN (the existing test only covers it on mount).
  • Nothing asserts that useBuddyConversation actually passes window.location.pathname. The new buddyService test calls streamMessage directly, and BuddyComposerIsolation only reads mock.calls[0][0]. Dropping the new argument in the hook would not fail any test.
  • Stale doc comments in AdminPage.tsx: the component docblock (~line 69) still says ?tab=projects "opens the page on that tab once", and the ?tab= comment still says it "seeds the tab once and is then stripped". Both now contradict the added paragraph.
  • ?projectId= / ?userId= are still handed off only on mount. With /admin?tab=projects&projectId=p1 followed while open, the tab switches but projectId stays in the URL and the drawer does not open (and a reload would then open it). That matches the comment, but the existing test name "without leaving anything in the URL" is only true on mount.

Overall this is a clean, low-risk PR. I would fix finding 1 before merge, since it is cheap and the buddy dock makes it easy to hit. Finding 2 can be fixed here or accepted as a documented limitation.

…wledge

# Conflicts:
#	src/services/buddyService.ts
@DavidLeuter
DavidLeuter merged commit 01450b7 into dev Oct 4, 2026
4 checks passed
@DavidLeuter
DavidLeuter deleted the feature/buddy-page-knowledge branch October 4, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants