Skip to content

Conversation

@jahorton
Copy link
Contributor

@jahorton jahorton commented Oct 13, 2025

This PR introduces a new implementation of the SearchQuotientNode type - SearchQuotientCluster. The SearchQuotientCluster type is designed to represent cases where two or more SearchQuotientNode instances represent the same total range of user input, as described in #15104's description as them "converging". In such cases, extending the search space by new input proceeds in exactly the same manner, regardless of which parent space is the original source. It's notably more efficient to cluster the paths together.

If it helps, reference https://github.com/keymanapp/keyman/blob/change/web/relocate-search-quotient-test-utils/web/src/engine/predictive-text/worker-thread/docs/correction-search-graph.md#the-searchquotientcluster-type. Each "codepoint length" block in that graph is its own SearchQuotientCluster, as well as the final, "destination" version visualized there.

Also note that SearchQuotientCluster directly reflects a TokenizationSubset (as described in #15140) - any of the paths leading to the cluster will correct to words of the same length, representing the same keystroke range from the user. Use of this type thus allows us to build a single ContextTokenization instance to represent the convergence of these paths - both for correction-search operations and for preservation of state after application of a suggestion arising from it.

Build-bot: skip build:web
Test-bot: skip

@keymanapp-test-bot
Copy link

keymanapp-test-bot bot commented Oct 13, 2025

User Test Results

Test specification and instructions

User tests are not required

Test Artifacts

  • Web
    • KeymanWeb Test Home - build : all tests passed (no artifacts on BuildLevel "build")

@keymanapp-test-bot keymanapp-test-bot bot added this to the A19S14 milestone Oct 13, 2025
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from 6ddd57f to 9068e40 Compare October 13, 2025 20:50
@jahorton jahorton force-pushed the refactor/web/simple-search-space-reuse branch from 1eaf922 to ddf9a58 Compare October 17, 2025 15:03
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from 9068e40 to b8457ec Compare October 17, 2025 15:10
@keymanapp-test-bot keymanapp-test-bot bot changed the title refactor(web): splits part of SearchSpace off into SearchPath refactor(web): splits part of SearchSpace off into SearchPath 🚂 Oct 17, 2025
@jahorton jahorton changed the base branch from refactor/web/simple-search-space-reuse to refactor/web/multi-space-correction-search October 17, 2025 15:10
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from 228d93a to f3fc256 Compare October 17, 2025 20:02
@jahorton jahorton changed the base branch from refactor/web/multi-space-correction-search to refactor/web/search-batcher October 17, 2025 20:03
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from f3fc256 to a6e14c5 Compare October 17, 2025 20:35
@jahorton jahorton changed the base branch from refactor/web/search-batcher to change/web/start-search-path October 17, 2025 20:36
@jahorton jahorton changed the base branch from change/web/start-search-path to refactor/web/multi-space-correction-search October 20, 2025 16:09
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from a6e14c5 to a03bc15 Compare October 20, 2025 18:18
@jahorton jahorton force-pushed the refactor/web/multi-space-correction-search branch from 02b9293 to 96a4b99 Compare October 21, 2025 19:14
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from a03bc15 to 3f199ce Compare October 21, 2025 21:00
@jahorton jahorton changed the title refactor(web): splits part of SearchSpace off into SearchPath 🚂 refactor(web): begin implementation of SearchCluster for merging paths reaching the same intermediate tokenization state 🚂 Oct 22, 2025
@jahorton jahorton force-pushed the refactor/web/multi-space-correction-search branch 2 times, most recently from 3fe8645 to de3d86c Compare October 23, 2025 21:36
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from 3f199ce to 0e70658 Compare October 24, 2025 18:43
@jahorton jahorton changed the base branch from refactor/web/multi-space-correction-search to refactor/web/search-path-merging October 24, 2025 18:43
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from 0e70658 to 72798ba Compare October 24, 2025 18:48
@darcywong00 darcywong00 modified the milestones: A19S14, A19S15 Oct 24, 2025
@keyman-server keyman-server added this to the A19S20 milestone Jan 3, 2026
@jahorton jahorton force-pushed the refactor/web/simplify-input-segments branch from f5f2c1c to 2521e83 Compare January 16, 2026 16:54
@keyman-server keyman-server modified the milestones: A19S20, A19S21 Jan 16, 2026
@jahorton jahorton force-pushed the refactor/web/simplify-input-segments branch from 2521e83 to c316ece Compare January 20, 2026 19:40
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch 2 times, most recently from eaac92f to 403721b Compare January 20, 2026 21:47
@jahorton jahorton force-pushed the refactor/web/simplify-input-segments branch from c316ece to 23cba38 Compare January 22, 2026 19:36
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from 403721b to fbe4bec Compare January 22, 2026 20:13
@jahorton jahorton force-pushed the refactor/web/simplify-input-segments branch from 23cba38 to 258e213 Compare January 23, 2026 18:07
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from 1d44f26 to 6306f5e Compare January 28, 2026 17:15
@jahorton jahorton force-pushed the refactor/web/simplify-input-segments branch 2 times, most recently from 237741f to cff287f Compare January 29, 2026 17:21
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch 2 times, most recently from bd5e4d9 to 7e1b6f4 Compare January 29, 2026 18:55
@keyman-server keyman-server modified the milestones: A19S21, A19S22 Jan 31, 2026
Base automatically changed from refactor/web/simplify-input-segments to epic/autocorrect February 5, 2026 14:54
@jahorton jahorton changed the title refactor(web): begin implementation of SearchCluster for merging paths reaching the same intermediate tokenization state 🚂 refactor(web): begin implementation of quotient-path convergence via SearchQuotientCluster 🚂 Feb 5, 2026
This is to prepare for corrections from alternate tokenizations that could result from fat-fingering whitespace keys or similar effects.

Build-bot: skip build:web
Test-bot: skip
@jahorton jahorton force-pushed the refactor/web/complex-search-space-reuse branch from 7e1b6f4 to d3857a1 Compare February 5, 2026 16:34
@jahorton jahorton changed the base branch from epic/autocorrect to change/web/relocate-search-quotient-test-utils February 5, 2026 16:35
@jahorton jahorton marked this pull request as ready for review February 5, 2026 16:37
Base automatically changed from change/web/relocate-search-quotient-test-utils to epic/autocorrect February 5, 2026 20:25
* manage the search-space(s) for text corrections within the engine.
*/

import { QueueComparator as Comparator, PriorityQueue } from '@keymanapp/web-utils';
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we please directly use QueueComparator?

Suggested change
import { QueueComparator as Comparator, PriorityQueue } from '@keymanapp/web-utils';
import { QueueComparator, PriorityQueue } from '@keymanapp/web-utils';

import { SearchNode, SearchResult } from './distance-modeler.js';
import { generateSpaceSeed, InputSegment, PathResult, SearchQuotientNode } from './search-quotient-node.js';

const PATH_QUEUE_COMPARATOR: Comparator<SearchQuotientNode> = (a, b) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const PATH_QUEUE_COMPARATOR: Comparator<SearchQuotientNode> = (a, b) => {
const PATH_QUEUE_COMPARATOR: QueueComparator<SearchQuotientNode> = (a, b) => {

readonly lowestPossibleSingleCost: number;

/**
* Constructs a fresh SearchSpace instance for used in predictive-text correction
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* Constructs a fresh SearchSpace instance for used in predictive-text correction
* Constructs a fresh SearchSpace instance for use in predictive-text correction

Comment on lines +59 to +60
* @param baseSpaceId
* @param model
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @param baseSpaceId
* @param model
* @param inboundPaths

* has fat-finger data available, which itself indicates that the user has
* corrections enabled.
*/
get correctionsEnabled(): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
get correctionsEnabled(): boolean {
get correctionsEnabled(): boolean {

});

it('handles case where tail token is split into three rather than two', function() {
it.skip('handles case where tail token is split into three rather than two', function() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess the skipped tests (in this and the other files) will be re-enabled in one of the following PRs?

*
* Created by jahorton on 2025-10-20
*
* This file defines the predictive-text engine's SearchSpace class, which is used to
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be ?

Suggested change
* This file defines the predictive-text engine's SearchSpace class, which is used to
* This file defines the predictive-text engine's SearchQuotientCluster class, which is used to

*
* Created by jahorton on 2025-10-29
*
* This file defines tests for the SearchSpace class of the
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* This file defines tests for the SearchSpace class of the
* This file defines tests for the SearchQuotientCluster class of the

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants