feat(create-from,github): materialize sheet + GitHub label/assignee pickers (G16, G18) - #74
Merged
Merged
Conversation
…ickers
Thread C: closes G16 ("Create from…") and G18 (GitHub metadata depth) from
work-consolidation.md. Stacked on refactor/apiclient-transport-seam — the new
endpoints live in `APIClient+*.swift` files, which that refactor made possible.
G16 — POST /api/materialize
- Models/Materialize.swift: the camelCase wire contract. `sourceKey` encodes as
an explicit null for user-added columns (the contract documents `string|null`,
and omission is a different thing).
- Services/MaterializePlanner.swift + MarkdownBlocks.swift: pure ports of the
backend's build-list.ts / markdown-blocks.ts, so the sheet's seeded columns and
preview match what the server will build. Optionless select/multiselect columns
are downgraded to text — the server's DSL validator rejects them outright, and
GitHub-backed lists hit exactly that with labels/assignees.
- Views/CreateFromSheet.swift + CreateFromColumnEditor.swift: destination picker
(List / Doc / Both), column rename/retype/remove/add, live preview, and the
created-result summary. Only ids go over the wire.
- Entry points: a message (detail), multi-select messages (feed), a whole list,
list rows (single via context menu, many via selection mode), and a document.
- Subscriber-gated: every entry point is hidden for free users, and a 403 maps to
neutral copy — the raw body carries "Subscribe…" text that must not appear
in-app (Guideline 3.1.1).
G18 — GitHub repo metadata
- APIClient+GitHub.swift: githubLabels / githubAssignees / githubOrgs /
githubNextIssueNumber. Orgs decode from either a bare array or an { orgs: [] }
envelope — production and the backend source currently disagree.
- ListItemFormView gains a `multiselect` case backed by real repo options;
ListDetailView fetches them and now shows labels/assignees instead of hiding
them. Falls back to free text when options can't load, and the write path is
unchanged — still the full-row `updateItem` proxy, never GitHub's issue routes
(a partial PUT renames the issue to "Untitled").
- CreateListView repo picker gains an org filter; list detail shows the next
issue number.
Shared: SelectionActionBar.swift extracts the selection row + bottom bar that the
feed and list detail both needed.
Verified: build green; 902 unit tests, 0 failures (823 baseline + 79 new);
app launches clean in the simulator with no runtime errors. Not yet driven by
hand against a live account — tapping Create writes real data to the shared test
account, so that pass is deliberately left to a human.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WFg1zPdWuasXD9ab6HJGHk
work-consolidation.md still listed G16 and G18 as open and G18 as partial. G15 landed in #43, G16/G18 in #74, G17 in #40. The file is superseded for open work by epic #44 (#45–#66), so this records status and the pointer rather than restating the epic here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017bss5MgZa7Jvj2m9zdaUd1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #45. Lands Thread C — G16 "Create from…" (materialize) and G18 GitHub metadata depth — which had been written but never opened as a PR.
What's here
One commit, 22 files (+2,704 / −45), rebased from its original base (
629662c) onto currentmain(4e168a2).POST /api/materialize.Models/Materialize.swift(camelCase wire contract,sourceKeyencodes an explicit null for user-added columns),MaterializePlanner+MarkdownBlocks(pure ports of the backend'sbuild-list.ts/markdown-blocks.tsso the seeded columns and preview match what the server builds),CreateFromSheet+CreateFromColumnEditor, and entry points on a message, a multi-message selection, a list, list rows (one via context menu, many via selection mode), and a document. Only ids go over the wire. Subscriber-gated at every entry point; a 403 maps to neutral copy so the body's "Subscribe…" text can't reach the UI (Guideline 3.1.1).APIClient+GitHub.swift:githubLabels/githubAssignees/githubOrgs/githubNextIssueNumber.ListItemFormViewgains amultiselectcase backed by real repo options;CreateListView's repo picker gains an org filter. The write path is unchanged — still the full-rowupdateItemproxy, never GitHub's issue routes.Rebase notes (4 conflicts, all resolved deliberately)
mainmoved 8 PRs since this branch was cut (#43 AI, #67 identity status, #68–#73).FeedView.swift#70'sonMute:callback ontoMessageRow.visibleMessagesnow filters throughisVisibleAuthorso it honours both the block list and the new mute list — previously it only checkedblockedUserIds.MessageDetailView.swift@State; theCreate from…sheet modifier is ordered ahead of#70's.muteConfirmation/.task.ListsView.swiftloadDataawaits both).project.pbxprojmainadded;plutil -lintclean and all 12 new files confirmed in the right target via thexcodeprojgem.Verification
iPhone 16UDID302E002E-…, dedicated-derivedDataPath,-parallel-testing-enabled NO, E2E skipped)..envaccount (messenger, subscriber), driven through the real app in the simulator. Every entry point confirmed present and correctly gated:Select posts→2 posts selected→ Create from… (correctly disabled at 0 selected)Post actions→ Create from…List actions→ Create from list…Select rows…→2 rows selected→ Create from…Document options→ Create from…The sheet shows the destination switch (To List / To Doc / To List & Doc), source summary, prefilled title, public/include-rows toggles, seeded columns with rename + retype + add, and a live preview of the real source data under an "Approximate — the server rebuilds every value" note.
content:textarea, author:text, posted:text, links:textarea, tags:text— exactly what the sheet's column editor showed — and 2 rows carrying the real content, author, timestamp and tags. The list was deleted afterwards; the account is back to its prior state.Not verified live
G18's label/assignee pickers. The
.envaccount has no GitHub connection —/api/github/reposand/api/github/orgsboth return200 []and none of its lists is GitHub-backed — so there was nothing live to point the pickers at. Covered byAPIClientGitHubMetadataTests(both the bare-array and{orgs:[]}response shapes), and the UI's documented fallback is to hide the multiselect rather than degrade to raw comma-separated text.🤖 Generated with Claude Code
https://claude.ai/code/session_017bss5MgZa7Jvj2m9zdaUd1