Skip to content

feat(search): a known prefix sends the query straight to its site, and ? lists the shortcuts - #785

Open
rubenvdlinde wants to merge 24 commits into
developmentfrom
feat/search-ai-prefix-shortcuts
Open

rubenvdlinde wants to merge 24 commits into
developmentfrom
feat/search-ai-prefix-shortcuts

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

What this does

Change search-ai-prefix-shortcuts (archived in this PR at openspec/changes/archive/2026-09-30-search-ai-prefix-shortcuts). Stacked on #784 (feat/launcher-tile-sorting): this branch contains every PR below it. Land the stack in order, or land the top PR with a merge commit and the ones below close with it.

  • Administrators define up to 30 search shortcuts on a new "Search shortcuts" admin tab: a prefix (! and 1 to 10 letters or digits, unique), a name, and an https address with {query}. The server refuses anything else ("Use an https address that contains {query}"). GET/PUT /api/admin/search-shortcuts, admin only.
  • The list reaches every page through the workspace initial state (searchShortcuts, optional key).
  • In a search widget, a query whose first word is a known prefix shows one result, "Search TOPdesk for printer 3e verdieping", and Enter opens the address with the encoded rest in a new tab (noopener). An unknown prefix filters tiles as before. ! or ? lists the shortcuts; Enter on one types its prefix.

Rows moved to built: d-search-prefix (built.change = openspec/changes/archive/2026-09-30-search-ai-prefix-shortcuts). The spec delta is folded into the main spec; the design records what the build corrected.

Tests (red first)

  • tests/Unit/Service/SearchShortcutServiceTest.php (prefix pattern, uniqueness, https template, limit, stale stored list); red run: 11 errors
  • tests/Unit/Service/InitialStateBuilderTest.php (the list reaches the workspace)
  • src/components/__tests__/RuntimeShellSearch.shortcuts.spec.js, src/components/admin/tabs/__tests__/SearchShortcutsTab.spec.js

Playwright tasks are not written; the specs carry @e2e exclude naming these files.

Verified

  • The stack now contains origin/development 5288399 (merged into feat(people): find colleagues by expertise and show extra profile fields #743 and up the stack; l10n catalogues merged per key, info.xml 1.1.7-unstable.20261005190000 for the whole stack, one migration Version002012).
  • Full local mirror of the required CI jobs on the stack top (feat/launcher-tile-internal-address): npm lint, format, check:manifest, check:schema-l10n, l10n-parity and Vitest (963 of 963) all 0 on 7579477; the later source changes are three @spec comments (eslint 0 on those files). composer check:strict (lint, phpcs, phpmd, psalm, phpstan, PHPUnit 1948 tests, 14 skipped database tests that run in CI) and phpmetrics: 0 on 4a17769, after fixing six phpmd findings the stack introduced: BookmarkImportController coupling and static access (4e44727), PageController::index() length and TileUpdater complexity (4a17769).
  • Hydra gates at CI's version (hydra-gates@main 4de7693, full scope, --require-full-coverage) on b2005d8: 85 of 86 applicable gates pass. Gate 16 found four untagged hooks, fixed where they were introduced (tile sorting, shortcuts, bookmarks). Gate 23 fails with the one match development itself has (PermissionService, RoleFeaturePermissionService, rule consume-or-rbac-fleet-wide); inherited, not touched here, and waiting on a decision.
  • No local production build; CI's Frontend Build is the check.

Live check

Admin settings, LaunchPad, "Search shortcuts": add !t, "TOPdesk", https://topdesk.example.nl/search?q={query}, save. In a search widget type !t printer 3e verdieping: one result, Enter opens ...?q=printer%203e%20verdieping in a new tab. Type ?: the shortcuts are listed. An http:// address is refused on save.

…ly, by most or last used, or at random

Most and last used read counts kept in the viewer's own browser, never sent to the
server; a viewer can forget them. The order is applied when the page is viewed and
never written back, and random holds for the page load.

REQ-TSO-001..004, REQ-CONT-007 (launcher-tile-sorting)
…ends a query straight to a site

search_shortcuts holds up to 30 entries {prefix, name, urlTemplate}; a prefix is !
and 1 to 10 letters or digits, unique; the address passes the https {query} check
the quick-search fallback already uses. The list reaches every page through the
workspace initial state.

REQ-QSP-001, REQ-QSP-002 (search-ai-prefix-shortcuts)
…d ? lists the shortcuts

In the search widget a query whose first word is a shortcut prefix shows one
result, Search TOPdesk for printer, and Enter opens the site in a new tab; an
unknown prefix filters tiles as before; ! or ? lists the shortcuts. Administrators
edit the list on a new admin tab.

REQ-SPX-001..003 (search-ai-prefix-shortcuts)
…e tile wrapper is not a fake control (gate-32)
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/launchpad @ 1712dd1

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
format ✅
check-schema-l10n ✅
composer ✅ ✅ 104/104
npm ✅ ✅ 636/636
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit ✅
Newman ✅
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development.
Hydra gates ❌

Quality workflow — 2026-10-05 18:06 UTC

Download the full PDF report from the workflow artifacts.

…tile-sorting

# Conflicts:
#	l10n/be.js
#	l10n/be.json
#	l10n/bg.js
#	l10n/bg.json
#	l10n/bs.js
#	l10n/bs.json
#	l10n/ca.js
#	l10n/ca.json
#	l10n/cs.js
#	l10n/cs.json
#	l10n/da.js
#	l10n/da.json
#	l10n/de.js
#	l10n/de.json
#	l10n/el.js
#	l10n/el.json
#	l10n/en.js
#	l10n/en.json
#	l10n/es.js
#	l10n/es.json
#	l10n/et.js
#	l10n/et.json
#	l10n/fi.js
#	l10n/fi.json
#	l10n/fr.js
#	l10n/fr.json
#	l10n/ga.js
#	l10n/ga.json
#	l10n/hr.js
#	l10n/hr.json
#	l10n/hu.js
#	l10n/hu.json
#	l10n/is.js
#	l10n/is.json
#	l10n/it.js
#	l10n/it.json
#	l10n/lb.js
#	l10n/lb.json
#	l10n/lt.js
#	l10n/lt.json
#	l10n/lv.js
#	l10n/lv.json
#	l10n/mk.js
#	l10n/mk.json
#	l10n/mt.js
#	l10n/mt.json
#	l10n/nb.js
#	l10n/nb.json
#	l10n/nl.js
#	l10n/nl.json
#	l10n/pl.js
#	l10n/pl.json
#	l10n/pt.js
#	l10n/pt.json
#	l10n/rm.js
#	l10n/rm.json
#	l10n/ro.js
#	l10n/ro.json
#	l10n/ru.js
#	l10n/ru.json
#	l10n/sk.js
#	l10n/sk.json
#	l10n/sl.js
#	l10n/sl.json
#	l10n/sq.js
#	l10n/sq.json
#	l10n/sr.js
#	l10n/sr.json
#	l10n/sv.js
#	l10n/sv.json
#	l10n/tr.js
#	l10n/tr.json
#	l10n/uk.js
#	l10n/uk.json
…shortcuts

# Conflicts:
#	l10n/be.js
#	l10n/be.json
#	l10n/bg.js
#	l10n/bg.json
#	l10n/bs.js
#	l10n/bs.json
#	l10n/ca.js
#	l10n/ca.json
#	l10n/cs.js
#	l10n/cs.json
#	l10n/da.js
#	l10n/da.json
#	l10n/de.js
#	l10n/de.json
#	l10n/el.js
#	l10n/el.json
#	l10n/en.js
#	l10n/en.json
#	l10n/es.js
#	l10n/es.json
#	l10n/et.js
#	l10n/et.json
#	l10n/fi.js
#	l10n/fi.json
#	l10n/fr.js
#	l10n/fr.json
#	l10n/ga.js
#	l10n/ga.json
#	l10n/hr.js
#	l10n/hr.json
#	l10n/hu.js
#	l10n/hu.json
#	l10n/is.js
#	l10n/is.json
#	l10n/it.js
#	l10n/it.json
#	l10n/lb.js
#	l10n/lb.json
#	l10n/lt.js
#	l10n/lt.json
#	l10n/lv.js
#	l10n/lv.json
#	l10n/mk.js
#	l10n/mk.json
#	l10n/mt.js
#	l10n/mt.json
#	l10n/nb.js
#	l10n/nb.json
#	l10n/nl.js
#	l10n/nl.json
#	l10n/pl.js
#	l10n/pl.json
#	l10n/pt.js
#	l10n/pt.json
#	l10n/rm.js
#	l10n/rm.json
#	l10n/ro.js
#	l10n/ro.json
#	l10n/ru.js
#	l10n/ru.json
#	l10n/sk.js
#	l10n/sk.json
#	l10n/sl.js
#	l10n/sl.json
#	l10n/sq.js
#	l10n/sq.json
#	l10n/sr.js
#	l10n/sr.json
#	l10n/sv.js
#	l10n/sv.json
#	l10n/tr.js
#	l10n/tr.json
#	l10n/uk.js
#	l10n/uk.json
#	lib/Controller/PageController.php
#	lib/Db/AdminSettingKey.php
#	lib/Service/InitialStateBuilder.php
#	src/components/admin/AdminSettings.vue
#	src/utils/loadInitialState.js
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/launchpad @ 8c1358b

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ❌
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
format ❌
check-schema-l10n ✅
composer ✅ ✅ 107/107
npm ❌ ✅ 636/636
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit ❌
Newman ❌
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development.
Hydra gates ❌

Quality workflow — 2026-10-23 05:24 UTC

Download the full PDF report from the workflow artifacts.

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.

1 participant