Skip to content

feat(lists): finish GitHub-backed list creation and add Refresh from GitHub #51

Description

@Adron

Summary

The macOS New List sheet shows GitHub source fields that do nothing:

App/Features/Lists/NewListSheetView.swift:85 — Section("GitHub source (optional)")
App/Features/Lists/NewListSheetView.swift:98 — Text("GitHub source fields will be sent in a future update.")

So a user can fill in a repo and get a plain local list. The web, meanwhile, has a full GitHub-backed list flow, and the client already ships the reading half (issue browser, create-issue-from-message, close/reopen, labels/assignees — G4 + the PR #24 route fixes).

The missing piece is creation and refresh.

What the web does (/help/lists)

Creating:

  • Prerequisite: GitHub connected with the Issues scope. "If you already linked GitHub for sign-in, you may need to click Reconnect for GitHub Issues to grant access."
  • On the GitHub-backed List tab, select a repository you have access to (a picker, not a free-text field)
  • List title defaults to the repo name
  • Optional parent list; optional Public toggle

Behaviour once created:

  • Rows map to issues (title, body, labels, assignees, state). Adding a row creates an issue; editing a row updates it; deleting a row closes it.
  • Schema is fixed — Edit changes only the parent list. "You cannot modify the issue fields … they are defined by GitHub."
  • Refresh from GitHub pulls the latest issues (the list caches locally).
  • Visibility is re-read from GitHub on every sync (create, manual refresh, scheduled sync).

Live facts (2026-09-07)

GET /api/github/repos        → 200 (test account is now GitHub-linked)  but the list is EMPTY
GET /api/github/orgs         → 200  []
GET /api/auth/github/status  → 200  {"configured":true,"clientId":"Ov23li9eXYK1i6psJW6G",
                                     "manageOrgAccessUrl":"https://github.com/settings/connections/applications/…"}

⚠️ The test account has no accessible repos, so the repo-picker payload and the githubSource-on-create request shape cannot be exercised end-to-end today. Before building, either grant the .env test account access to a repo, or capture the web app's own network calls for a create. Do not guess the create-time field names — work-consolidation.md P3-C records githubSource: { owner, repo, path, ref } as unconfirmed.

Also unconfirmed (P3-C)

The refresh metadata the UI needs — lastRefreshedAt, refreshStatus (idle|pending|failed), refreshError — is modelled in the domain as GitHubListSource but has never been seen on the wire. Probe before rendering a refresh state, or render only what is actually returned.

Division of labor

Kit

  • Accept githubSource on POST /api/lists once the shape is confirmed.
  • A repo-picker request builder over GET /api/github/repos (already present — confirm the populated shape against a repo-bearing account).
  • Whatever route drives Refresh from GitHub; if none exists, file the backend ask rather than inventing one.
  • Contract tests against a repo-bearing account.

Domain

  • Extend list creation with a GitHub source, gated on the subscriber entitlement and on a GitHub identity with Issues scope.
  • Model the fixed-schema rule so the schema editor refuses field edits on a GitHub-backed list and offers only the parent-list change.
  • Refresh action + refresh state, only for the fields the probe confirms.

App

  • Replace the dead GitHub section in NewListSheetView with a real repo picker populated from the account's repos, plus the title default.
  • An inline Reconnect for GitHub Issues CTA when the identity lacks the scope — reuse the OAuth flow from the Integrations issue rather than building a second one.
  • Refresh from GitHub in the list toolbar, with its state surfaced.
  • Schema editor: parent-list-only mode for GitHub-backed lists, with an explanation rather than a silently disabled form.

Tests

  • happy — pick a repo, create the list, rows arrive as issues
  • invalid — GitHub not linked, or linked without Issues scope → the reconnect CTA, no create attempt
  • upstream-failure — the repo list 500s → the picker shows an error and the local-list tab still works
  • boundary — an account with zero accessible repos (today's test account) → an honest empty picker, not a spinner

Acceptance criteria

  • No control in the New List sheet promises something "in a future update".
  • A GitHub-backed list created on the Mac behaves the same as one created on the web.
  • Full E2E gate green.

Notes

New finding from the 2026-09-07 parity sweep. Depends on P3-C (create-time and refresh shapes) and shares the OAuth scope-upgrade flow with the Integrations issue. Size M.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestparityWeb-parity gap with the InterlinedList web app

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions