Skip to content

Filter acceptance tests for installation token capabilities - #14354

Merged
williammartin merged 2 commits into
trunkfrom
williammartin-acceptance-token-capabilities
Sep 9, 2026
Merged

williammartin merged 2 commits into
trunkfrom
williammartin-acceptance-token-capabilities

Conversation

@williammartin

@williammartin williammartin commented Sep 4, 2026 •

Copy link
Copy Markdown
Member

Depends on #14320.

Description

GitHub App installation tokens cannot perform operations that require a user account, so running the complete acceptance suite with one currently attempts unsupported user-only behavior. The intention is not for this to be a total solution to pruning test trees, but to allow us to unlock running this in CI in a not totally bonkers way.

This middle layer adds explicit per-script metadata describing whether a user-authenticating token is required. The harness classifies OAuth, classic PAT, fine-grained PAT, and GitHub App user tokens as user-capable, while treating GitHub App installation tokens as installation-only and filtering incompatible scripts. Unsupported token prefixes fail explicitly. As a result, an installation token can run the compatible suite without being granted or attempting user-only behavior.

This PR is the middle layer of a three-layer native stack. It depends on #14320 and intentionally does not add the GitHub Actions workflow.

How did you test this change?

OAuth Token

➜ GH_ACCEPTANCE_HOST=github.com \
  GH_ACCEPTANCE_ORG=gh-acceptance-testing \
  GH_ACCEPTANCE_TOKEN="$(gh auth token --hostname github.com)" \
  go test -tags=acceptance -count=1 ./acceptance
ok      github.com/cli/cli/v2/acceptance        366.276s

Installation Token

Minted using gh token generate and stored in GH_ACCEPTANCE_TOKEN:

➜ GH_ACCEPTANCE_HOST=github.com \
  GH_ACCEPTANCE_ORG=gh-acceptance-testing \
  go test -tags=acceptance -count=1 ./acceptance
ok    github.com/cli/cli/v2/acceptance        325.755s

I exercised the new metadata lint by temporarily adding acceptance/testdata/api/zzz-linter-missing-user-capability.txtar containing only fixture-repo none, without the required capability header. I ran the following command and saw it reject the script (output excerpt; local absolute-path error trace omitted):

$ go test ./acceptance -run '^TestAcceptanceScriptsDeclareUserCapabilityRequirement$' -count=1
--- FAIL: TestAcceptanceScriptsDeclareUserCapabilityRequirement (0.04s)
    --- FAIL: TestAcceptanceScriptsDeclareUserCapabilityRequirement/testdata/api/zzz-linter-missing-user-capability.txtar (0.00s)
        user_capability_test.go:163:
            Error:       Received unexpected error:
                         testdata/api/zzz-linter-missing-user-capability.txtar: first line must be '# requires-user-capability: true' or '# requires-user-capability: false'
            Test:        TestAcceptanceScriptsDeclareUserCapabilityRequirement/testdata/api/zzz-linter-missing-user-capability.txtar
FAIL
FAIL    github.com/cli/cli/v2/acceptance    0.423s
FAIL

I removed the temporary script afterward. This only exercised local metadata validation; it did not run live acceptance tests or access GitHub resources.

Key points

  • Every acceptance script must declare its user capability requirement on the first line, making compatibility explicit and mechanically validated.
  • Explicitly selecting an incompatible script fails with a targeted message; unfiltered installation-token runs omit incompatible scripts.
  • Existing fixture declarations, organization scoping, shared-state safety, clone reductions, and public-repository behavior from Reduce rate limiting and reduce time taken for acceptance tests #14320 are preserved.

Notes for reviewers

Start with acceptance/user_capability_test.go for token classification and metadata validation, then read the filtering path in acceptance/acceptance_test.go. Review #14320 first for the fixture and performance foundation this layer builds on.

I will say that I did see quite some flaky behaviour, but I'm content to merge this and do burn down.

Authorship and follow-up

Who wrote this:

  • A human wrote it.
  • An agent wrote it under close human direction.
  • An agent wrote it independently, and no human has guided the implementation beyond the initial prompt.

Who answers review comments:

  • @williammartin will read and reply directly. Name the account.
  • An agent will draft replies and @username will read them before they are posted.
  • Nobody has explicitly committed to replying.

Copilot AI balanced review requested due to automatic review settings September 8, 2026 14:31
@williammartin
williammartin force-pushed the williammartin-acceptance-token-capabilities branch from a119f60 to 2cb5bd0 Compare September 8, 2026 14:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Core filtering lacks required coverage, and metadata validation permits duplicate declarations.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 2 Medium severity

New issues introduced by this change (2)
Severity Finding
Medium severity acceptance/​acceptance_test.go — 🛑 Requirement: The core filtering behavior is not exercised by a test. Existing tests cover token…
Medium severity acceptance/​user_capability_test.go — 🛑 Requirement: The validator does not enforce the documented "exactly one" capability declaration.…
What changed in this PR

Adds installation-token-aware acceptance-test filtering while preserving user-only coverage.

Changes:

  • Classifies token capabilities and filters incompatible scripts.
  • Adds capability metadata to acceptance scripts and documentation.
  • Updates go-internal for improved token redaction.
File Review
go.sum Updates dependency checksums.
go.mod Updates go-internal.
acceptance/​user_capability_test.go Adds token classification and metadata validation; must reuse centralized token types and reject duplicate declarations.
acceptance/​testdata/​workflow/​workflow-view.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​workflow-run.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​workflow-list.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​workflow-enable-disable.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​run-view.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​run-view-log-escape-sequences.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​run-rerun.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​run-download.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​run-delete.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​run-cancel.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​cache-list-empty.txtar Adds capability metadata.
acceptance/​testdata/​workflow/​cache-list-delete.txtar Adds capability metadata.
acceptance/​testdata/​variable/​variable-repo.txtar Adds capability metadata.
acceptance/​testdata/​variable/​variable-repo-env.txtar Adds capability metadata.
acceptance/​testdata/​variable/​variable-org.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​telemetry-for-official-extension-stub.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​telemetry-failure-does-not-break-command.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​no-telemetry-for-send-telemetry.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​no-telemetry-for-ghes-user.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​no-telemetry-for-extension.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​no-telemetry-for-completion.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​no-telemetry-for-alias.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​command-invocation.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​agent-dimensions.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​accessibility-dimensions.txtar Adds capability metadata.
acceptance/​testdata/​telemetry/​accessibility-dimensions-disabled.txtar Adds capability metadata.
acceptance/​testdata/​ssh-key/​ssh-key.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-update.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-update-noinstalled.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-update-inplace.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-search.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-search-page.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-search-noresults.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-publish-lifecycle.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-publish-dry-run.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-publish-dir-remote.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-preview.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-preview-noninteractive.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install-scope.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install-pin.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install-nonexistent-skill.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install-nested-files.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install-namespaced.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install-invalid-repo.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install-invalid-agent.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install-from-local.txtar Adds capability metadata.
acceptance/​testdata/​skills/​skills-install-force.txtar Adds capability metadata.
acceptance/​testdata/​secret/​secret-require-remote-disambiguation.txtar Adds capability metadata.
acceptance/​testdata/​secret/​secret-repo.txtar Adds capability metadata.
acceptance/​testdata/​secret/​secret-repo-env.txtar Adds capability metadata.
acceptance/​testdata/​secret/​secret-org.txtar Adds capability metadata.
acceptance/​testdata/​secret/​secret-org-with-selected-visibility.txtar Adds capability metadata.
acceptance/​testdata/​search/​search-issues.txtar Adds capability metadata.
acceptance/​testdata/​ruleset/​ruleset.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-sync.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-sync-worktree.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-set-default.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-rename-transfer-ownership.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-read-file.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-read-dir.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-list-rename.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-fork-sync.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-edit.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-deploy-key.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-delete.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-create-view.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-create-bare.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-clone.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-autolink.txtar Adds capability metadata.
acceptance/​testdata/​repo/​repo-archive-unarchive.txtar Adds capability metadata.
acceptance/​testdata/​release/​release-view.txtar Adds capability metadata.
acceptance/​testdata/​release/​release-upload-download.txtar Adds capability metadata.
acceptance/​testdata/​release/​release-list.txtar Adds capability metadata.
acceptance/​testdata/​release/​release-delete.txtar Adds capability metadata.
acceptance/​testdata/​release/​release-create.txtar Adds capability metadata.
acceptance/​testdata/​project/​project-create-delete.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-view.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-view-status-respects-simple-pushdefault.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-view-status-respects-remote-pushdefault.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-view-status-respects-push-destination.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-view-status-respects-branch-pushremote.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-view-same-org-fork.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-view-outside-repo.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-status-respects-cross-org.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-merge-rebase-strategy.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-merge-merge-strategy.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-list.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-without-upstream-config.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-with-metadata.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-respects-user-colon-branch-syntax.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-respects-simple-pushdefault.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-respects-remote-pushdefault.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-respects-push-destination.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-respects-branch-pushremote.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-remote-ref-with-branch-name-slash.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-push-default-upstream-no-merge-ref.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-push-default-upstream-no-merge-ref-fork.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-no-local-repo.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-guesses-remote-from-sha.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-guesses-remote-from-sha-with-branch-name-slash.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-from-manual-merge-base.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-from-issue-develop-base.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-edit-with-project.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-create-basic.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-comment-new.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-comment-edit-last-without-comments-errors.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-comment-edit-last-without-comments-creates.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-comment-edit-last-with-comments.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-checkout.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-checkout-worktree.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-checkout-worktree-from-fork.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-checkout-worktree-detach.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-checkout-with-url-from-fork.txtar Adds capability metadata.
acceptance/​testdata/​pr/​pr-checkout-by-number.txtar Adds capability metadata.
acceptance/​testdata/​org/​org-list.txtar Adds capability metadata.
acceptance/​testdata/​label/​label.txtar Adds capability metadata.
acceptance/​testdata/​issues-2.0/​issue-view-issues-2.0-fields.txtar Adds capability metadata.
acceptance/​testdata/​issues-2.0/​issue-list-filter-by-type.txtar Adds capability metadata.
acceptance/​testdata/​issues-2.0/​issue-edit-sub-issues.txtar Adds capability metadata.
acceptance/​testdata/​issues-2.0/​issue-create-and-edit-relationships.txtar Adds capability metadata.
acceptance/​testdata/​issues-2.0/​issue-create-and-edit-parent.txtar Adds capability metadata.
acceptance/​testdata/​issues-2.0/​issue-create-and-edit-issue-type.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-view.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-list.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-develop-worktree.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-develop-worktree-cross-repo.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-create-with-metadata.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-create-edit-with-project.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-create-basic.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-comment-new.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-comment-edit-last-without-comments-errors.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-comment-edit-last-without-comments-creates.txtar Adds capability metadata.
acceptance/​testdata/​issue/​issue-comment-edit-last-with-comments.txtar Adds capability metadata.
acceptance/​testdata/​gpg-key/​gpg-key.txtar Adds capability metadata.
acceptance/​testdata/​gist/​gist-edit-rename-list.txtar Adds capability metadata.
acceptance/​testdata/​gist/​gist-create-view-delete.txtar Adds capability metadata.
acceptance/​testdata/​extension/​extension.txtar Adds capability metadata.
acceptance/​testdata/​extension/​extension-env.txtar Adds capability metadata.
acceptance/​testdata/​discussion/​discussion-view.txtar Adds capability metadata.
acceptance/​testdata/​discussion/​discussion-list.txtar Adds capability metadata.
acceptance/​testdata/​discussion/​discussion-edit.txtar Adds capability metadata.
acceptance/​testdata/​discussion/​discussion-create.txtar Adds capability metadata.
acceptance/​testdata/​discussion/​discussion-comment.txtar Adds capability metadata.
acceptance/​testdata/​auth/​auth-token.txtar Adds capability metadata.
acceptance/​testdata/​auth/​auth-status.txtar Adds capability metadata.
acceptance/​testdata/​auth/​auth-setup-git.txtar Adds capability metadata.
acceptance/​testdata/​auth/​auth-login-logout.txtar Adds capability metadata.
acceptance/​testdata/​api/​basic-rest.txtar Adds capability metadata.
acceptance/​testdata/​api/​basic-graphql.txtar Adds capability metadata.
acceptance/​README.md Documents classification and filtering.
acceptance/​acceptance_test.go Implements filtering; core filtering branches require table-driven coverage.
.github/​skills/​writing-acceptance-tests/​SKILL.md Documents capability metadata requirements.
Suppressed comments (2)

acceptance/user_capability_test.go:27

  • 🛑 Requirement: This recreates the credential-prefix definitions already centralized in internal/gh/gh.go:111-130. Refer to the existing TokenType constants here so capability classification cannot drift when the recognized token formats change; this function only needs to map those token types to user capability.
    acceptance/user_capability_test.go:118
  • 🛑 Requirement: Use require.EqualError for this error assertion. AGENTS.md:116 requires require rather than assert for error checks so the test stops immediately when the expectation fails.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread acceptance/acceptance_test.go Outdated
Comment thread acceptance/user_capability_test.go Outdated
@williammartin
williammartin force-pushed the williammartin-acceptance-token-capabilities branch 6 times, most recently from a6f38b5 to a25c181 Compare September 8, 2026 18:42
@williammartin
williammartin force-pushed the williammartin-acceptance-token-capabilities branch 9 times, most recently from e1d87ba to f6e0d8f Compare September 9, 2026 14:13
Base automatically changed from williammartin-workflow-run-acceptance to trunk September 9, 2026 14:37
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f67f4129-93de-45b1-a68d-702334aa7fe9
@williammartin
williammartin force-pushed the williammartin-acceptance-token-capabilities branch from f6e0d8f to 6dc60bf Compare September 9, 2026 14:37
@williammartin
williammartin marked this pull request as ready for review September 9, 2026 15:32
@williammartin
williammartin requested a review from a team as a code owner September 9, 2026 15:32
@williammartin
williammartin requested review from babakks and sergiou87 and a balanced review from Copilot and removed request for sergiou87 September 9, 2026 15:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The capability parser’s returned values lack direct tests, allowing inverted script filtering to pass unnoticed.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 1 Medium severity · 2 Low severity

New issues introduced by this change (3)
Severity Finding
Medium severity acceptance/​user_capability_test.go — 🛑 Requirement: The parser’s valid results are never asserted. Every call here discards the returned…
Low severity acceptance/​README.md — 💭 Commentary: This says user-only scripts are always skipped, but an explicitly selected…
Low severity go.mod — 💭 Commentary: This is not a redaction-only dependency update: the version jump also absorbs roughly…
Issues resolved since last review (2)
Severity Finding
Medium severity acceptance/​user_capability_test.go — 🛑 Requirement: The validator does not enforce the documented "exactly one" capability declaration.… View resolved comment
Medium severity acceptance/​acceptance_test.go — 🛑 Requirement: The core filtering behavior is not exercised by a test. Existing tests cover token… View resolved comment

Comment thread acceptance/user_capability_test.go Outdated
Comment thread acceptance/README.md Outdated
Comment thread go.mod Outdated

@babakks babakks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

Comment on lines +50 to +56
scanner := bufio.NewScanner(f)
if !scanner.Scan() {
if err := scanner.Err(); err != nil {
return false, err
}
return false, fmt.Errorf("%s: first line must be '# requires-user-capability: true' or '# requires-user-capability: false'", file)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nitpick: I know it's easier this way, but let's allow any number of lines at the top starting with #, and then a blank line, and then don't expect a fix ordering of directives.

Also, a valid file should be exactly like this:

# directive1:
# directive2:
...
# directiveN:

# rest of the file

The directives should all be known values, and the blank is necessary.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think we should do that when it's needed. I'm not even sure the directive will stick around the way it is.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d59cb8ae-bb43-4e07-8950-2e75cd3c3e75
@williammartin
williammartin merged commit e18cc33 into trunk Sep 9, 2026
18 checks passed
@williammartin
williammartin deleted the williammartin-acceptance-token-capabilities branch September 9, 2026 17:52
ripta added a commit to ripta/prowling that referenced this pull request Sep 16, 2026
Most revisions on a pull request carry no conversation. Seventeen of the
nineteen on cli/cli#14354 are force-pushes nobody commented on. Opening one
changed the glyph and nothing else. The fold then looked broken.

A revision row now counts the items it holds. One holding nothing draws no
glyph, and the key does nothing rather than flipping a state with no visible
effect.

The view opens on the newest revision holding conversation. The last push
usually lands after the last review, so the newest revision is empty on three
of the four fixtures.

The window reaches for the last row of the group the cursor sits on. Expanding
at the bottom edge otherwise drew every item below the fold, leaving the
footer's count as the only thing that moved.

Movement steps from the cursor the updater is handed. A held key batches its
presses into one render, and reading the closure moved the cursor a single step
however many arrived.
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.

3 participants