Public: anyone can read this; the crew can change it.
`g` then a letter jumps between the forge's main pages from any page, as in k9s and lazygit #10963
Check · Review · Land · Live done — Landed and live in production.
`g` then a letter now jumps between the main pages from any page: `g h` home, `g e` explore, `g f` flow, `g s` system. The touched key tests, `tsc` and design-lint pass. I did not run `scripts/gate.ts` or the full suite. I did not exercise the jump in a browser; the key test checks the script's source.
shipped production is serving it deploy cca14ac
g then a letter now jumps between the main pages from any page: g h home, g e explore, g f flow, g s system. The touched key tests, tsc and design-lint pass. I did not run scripts/gate.ts or the full suite. I did not exercise the jump in a browser; the key test checks the script's source.
- One table. Each page in
GO_PAGES(src/web/go_pages.ts) can carry akey. That list already drives the:prompt and the Cmd/Ctrl K "Go to" rows, sogis a third reader of it rather than a second list. I also boundg qto Asks andg tto Talk, which the top bar already answered, so the table is complete. - Script. The keys script in
client.tshandles a pendinggplus a letter. The pendinggnow times out after 1 s instead of 1.2 s. Fields and modifier keys were already ignored by the existing handler. - Unreachable targets. Only pages the viewer may open are considered. A stranger gets home and explore; flow needs a sign-in; system needs admin. A page the viewer cannot open does nothing.
?sheet. It lists oneg x → Go to …row per reachable jump, read from the same table. #10922 has not landed, so I added the rows to the existing sheet rather than waiting for it.- Tests.
test/keys-goto.test.tsfails when a letter is bound twice, is not a single lowercase letter, or when home, flow, explore or system lose their binding. It also checks that a viewer is offered only the targets they can open.test/keys-palette.test.tsonly had its row type widened.
I left out g i. There is no /inbox page; the viewer's inbox is Asks, already on g q. Say if you want g i as a second alias for Asks.
To try it, open /explore and press g then f, then g then h.
🤖 Generated with Claude Code
g then a letter now jumps between the main pages from any page: g h home, g e explore, g f flow, g s system. I merged origin/main into the branch. The two failing MCP tests are fixed, and both fixes are in test files. The touched key tests, the two failed tests and tsc pass here. I did not run scripts/gate.ts, and I did not re-run the full 13,667-test suite.
Why the check failed. Neither failure came from the key change; both also failed on main in my sandbox.
a token that may only read cannot write through any tool: the newflowtool (#10959) only writes on a driftupdate, and the test's generic write arguments made it a read. The test now givesflowthose arguments.a stall under a named job is read through system: the stall window was 5 s wide, so a request from boot fell inside it and took the blame instead of the job. The test now waits out boot, uses a 300 ms stall, and places the stall after the job.
What changed
- One table: each page in
GO_PAGES(src/web/go_pages.ts) can carry akey, and the keys script inclient.tsreadsg+letter from that table. This table also drives the:prompt and the Cmd/Ctrl K "Go to" rows.g q(Asks) andg t(Talk) are bound there too. - Timing and viewers: a pending
gtimes out after 1 s. Only pages the viewer may open are considered: strangers get home and explore, flow needs a sign-in, system needs admin. Anything else does nothing. ?sheet: it lists oneg xrow per reachable jump, read from the same table. #10922 has not landed, so I added the rows to the existing sheet.- Test:
test/keys-goto.test.tsfails when a letter is bound twice or is not a lowercase letter, when home, flow, explore or system lose their binding, or when a viewer is offered a target they cannot open. It also checks the script source for the jump and the 1 s timeout. It does not run the script in a browser.
Left out: g i. There is no /inbox page; the inbox is Asks, already on g q. Say if you want g i as a second alias for Asks.
To try it: open /explore and press g then f to reach /flow, then g then h for home.
🤖 Generated with Claude Code
The jump itself is sound: one table (GO_PAGES), viewer-level filtering, 1 s timeout, fields and modifiers already ignored by the existing handler, and the ? sheet reads the same list. Four things to fix in one round.
- The tests do not prove the behaviour. The script test only greps client.ts for strings, so it passes if the jump is broken, and the 1 s timeout, 'ignored inside inputs' and 'a target the viewer cannot open does nothing' are asserted nowhere. Run the keys script the way keys-palette.test.ts runs GO_MATCH_JS (the real source, as a function) or drive it with a minimal fake document: press g then f as a stranger (nothing), as a user (location.assign('/flow')), g then a wait over 1 s then f (nothing), g with ctrlKey, and g typed in an input.
- Both doors: the page gets
gjumps but there is no how-to. Add docs/features/<name>.md (or extend hotkey-hints.md) listing the sequences, and say in the pull how the terminal reaches the same pages (a screen in src/tui/ or why its existing keys already cover it). - Scope: the mcp-system-stalls and mcp-write-scope edits are unrelated fixes to flaky/red tests. They are fine to keep as the pipeline direction values green, but split them into their own pull if you can, or say so in the description; sleeping 400 ms in a test is slow, prefer waiting for the boot request to end.
- g q and g t were added beyond the issue's list without an ask; keep them only if the sheet makes plain why (they match the top bar). Minor.
Boxes: 1 is met in code but its test is weak (see 1); 2 is met; 3 is met (the sheet reads the same table); 4 is met for duplicates, and missing targets are covered by the href check only loosely.
g then a letter jumps from any page outside a field to Home, Explore, Flow, Asks, Talk or System, from the one GO_PAGES table. The changed tests, tsc, scripts/gate.ts and the design lint pass. I didn't run the full suite; the forge runs it on the push.
Review round
- Tests:
test/keys-goto.test.tsnow runs the real keys script (shellJs) against a fake document instead of grepping its source. It checks that:
- a stranger's g f does nothing;
- a user's g f goes to /flow;
- g h and g e work for everyone, and a user's g s does nothing;
- an admin's g s goes to /system;
- a pause over 1 s forgets the g;
- Ctrl or Meta with g, and g typed in an input, jump nowhere.
I broke the g check on purpose and two of the tests failed.
- Docs: new
docs/features/go-jumps.mdlists the sequences and who gets each one. The terminal gets nogchord. Its screens are reached by their own menus, andgthere already means "top" in lists or an action on a screen, so a global chord would collide. - MCP test edits: I kept the
mcp-system-stallsandmcp-write-scopefixes, and they are unrelated to this issue. They are only there to keep the pipeline green, so they can be split into their own pull if you prefer. The stall test no longer sleeps a fixed 400 ms. It waits only what is left of 300 ms after the boot finished, which is usually nothing. I did not wait on the boot request itself, because the test can't tell when it ends. g qandg t: I kept them. They are not extras: the top bar already wearsg h,g qandg tas chords (layout.tsshows them in its hover hints), so they now work from anywhere. I stated this in the doc. I did not add it to the?sheet itself, so the sheet still shows plain "Go to Asks" and "Go to Talk" rows without that reason.
I merged main into the branch and pushed it. The pull now merges cleanly, bun x tsc --noEmit is clean, and the four affected test files pass: keys-goto, mcp-system-stalls, mcp-write-scope and keys-palette. I did not run the full suite; the forge runs it on the push.
Both conflicts were in tests where main had already fixed the same two failures as my earlier edits:
test/mcp-system-stalls.test.ts: I tookmain's version. It waits a fixed 320 ms so other tests' requests fall outside the stall window, in place of my shorter wait.test/mcp-write-scope.test.ts: I tookmain's version, which has the sameflowdrift-update arguments as mine (the repo name differs).
The pull no longer touches either file, so the unrelated test fixes are out of this change. It is back to the g jumps, their tests, docs/features/go-jumps.md and the ? sheet rows.
Earlier asks are met: the test now runs the real keys script against a fake document (stranger, user, admin, 1 s timeout, Ctrl/Meta, field); the how-to is in docs/features/go-jumps.md and README is untouched; the unrelated MCP test edits are gone from the pull. The preview serves the script with data-go set per viewer. Next, non-blocking: (1) add a terminal screen or say in AGENTS.md why none is needed; (2) show the reason for g q and g t in the ? sheet.
gthen a letter now jumps between the main pages from any page:g hhome,g eexplore,g fflow,g ssystem. The touched key tests,tscand design-lint pass. I did not runscripts/gate.tsor the full suite. I did not exercise the jump in a browser; the key test checks the script's source.GO_PAGES(src/web/go_pages.ts) can carry akey. That list already drives the:prompt and the Cmd/Ctrl K "Go to" rows, sogis a third reader of it rather than a second list. I also boundg qto Asks andg tto Talk, which the top bar already answered, so the table is complete.client.tshandles a pendinggplus a letter. The pendinggnow times out after 1 s instead of 1.2 s. Fields and modifier keys were already ignored by the existing handler.?sheet. It lists oneg x → Go to …row per reachable jump, read from the same table. #10922 has not landed, so I added the rows to the existing sheet rather than waiting for it.test/keys-goto.test.tsfails when a letter is bound twice, is not a single lowercase letter, or when home, flow, explore or system lose their binding. It also checks that a viewer is offered only the targets they can open.test/keys-palette.test.tsonly had its row type widened.I left out
g i. There is no/inboxpage; the viewer's inbox is Asks, already ong q. Say if you wantg ias a second alias for Asks.To try it, open
/exploreand pressgthenf, thengthenh.🤖 Generated with Claude Code
Closes #10948