Skip to content

feat(import): csv type column and artist-less rows - #443

Open
chiptus wants to merge 17 commits into
mainfrom
claude/link-wizard-enhancements-uhez0n
Open

feat(import): csv type column and artist-less rows#443
chiptus wants to merge 17 commits into
mainfrom
claude/link-wizard-enhancements-uhez0n

Conversation

@chiptus

@chiptus chiptus commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Schedule import handles typed lineups (#433): an optional Type CSV column is validated, named artist-less rows import and re-match by name + date/stage against 0-artist sets only, an explicit type overwrites while a blank preserves, and the diff review shows stored → incoming type chips.

Closes #433

Verification

  • Import a CSV with a Type column (e.g. workshop); the diff review lists the set with a type chip, and after commit the set carries that type.
  • Import a row with a Set Name but no artists; it imports, and re-importing the same CSV updates it instead of duplicating it.
  • Re-import a typed set with the Type cell blank; the stored type is kept. Re-import with a different type; the chips show stored → incoming and commit overwrites it.
  • Import a CSV with an invalid type (e.g. concert); parsing fails with an error naming the value.
  • A row with neither artists nor a set name is skipped, as before.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TL2F1n6R7dmSfQiMbornRG


Generated by Claude Code

claude added 3 commits August 27, 2026 20:34
CSV imports accept an optional Type column (blank keeps the stored
type, invalid values fail parsing) and keep named artist-less rows,
matching them by name + date/stage against 0-artist sets only so
workshops survive re-imports. The diff review lists type chips for
verification before commit.

Closes #433

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TL2F1n6R7dmSfQiMbornRG
Review follow-ups: both edge functions validate against a shared
_shared/setTypes.ts vocabulary, the client payload schema uses the
SET_TYPES enum instead of raw strings, and update rows in the diff
review show stored → incoming type chips so type changes are
verifiable.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TL2F1n6R7dmSfQiMbornRG
Copilot AI lite review requested due to automatic review settings August 27, 2026 20:55
@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
upline Ready Ready Preview Aug 28, 2026 8:04pm

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown

Deploy → stagingworkflow run
Last updated: 2026-08-28 20:07:41 UTC

  • DB migrations succeeded
  • Edge functions succeeded

Comment thread docs/handoffs/link-wizard-376.md Outdated

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.

🟡 Changes recommended

It includes an unrelated handoff doc and a few type/contract narrowings should be fixed to keep the schedule diff/commit pipeline consistently typed.

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

Pull request overview

Adds support for importing and committing non-music “set types” and artist-less schedule rows (e.g. workshops) across the CSV parse → diff preview → commit pipeline, including UI diff chips to verify type changes before committing.

Changes:

  • Accepts optional Type CSV column (validated against known set types) and carries it through to the commit payload with “blank preserves stored / explicit overwrites” semantics.
  • Allows importing and re-matching named artist-less rows by name + date/stage against existing 0-artist sets only (avoiding roster/artist-less cross-matches).
  • Enhances diff review UI to show stored → incoming type chips for explicit type rows.
File summaries
File Description
supabase/migrations/20260827210000_commit_schedule_set_type.sql Updates commit RPC helpers to support writing sets.set_type and syncing empty artist rosters safely.
supabase/functions/diff-schedule/types.ts Extends diff function types to include set_type and track previousSetType for review UI.
supabase/functions/diff-schedule/resolvers.ts Adds separate indexing for artist-less sets to ensure correct matching behavior.
supabase/functions/diff-schedule/resolvers.test.ts Updates test fixtures to include set_type on sets.
supabase/functions/diff-schedule/index.ts Validates incoming CSV rows for optional setType and selects set_type from DB.
supabase/functions/diff-schedule/computeDiff.ts Computes payload name + setType, and switches matching logic for artist-less rows.
supabase/functions/diff-schedule/computeDiff.test.ts Adds unit tests covering type payload behavior + artist-less matching semantics.
supabase/functions/commit-schedule/index.ts Validates commit payloads for setType and allows empty artistSlugs.
supabase/functions/commit-schedule/commit-schedule.test.ts Adds integration tests for artist-less typed set creation and overwrite/preserve semantics.
supabase/functions/_shared/setTypes.ts Introduces shared SET_TYPES/SetType for edge functions.
src/services/scheduleImport/types.ts Extends client schemas/types for setType and previousSetType in diff results.
src/services/scheduleImport/parseCsv.ts Parses Type column, retains named artist-less rows, and validates sluggability of set names.
src/services/scheduleImport/parseCsv.test.ts Adds tests for type parsing, artist-less row retention, and invalid inputs.
src/services/scheduleImport/buildCommitPayload.test.ts Ensures setType + empty rosters flow through to commit payloads.
src/components/Admin/ScheduleImport/TypedSetsPanel.tsx Adds a diff-review panel rendering type chips (stored → incoming) for typed rows.
src/components/Admin/ScheduleImport/DiffReviewStep.tsx Wires the typed-sets panel into the diff review step.
src/components/Admin/ScheduleImport/CsvDropZone.tsx Updates CSV instructions to mention Type and artist-less row handling.
docs/handoffs/link-wizard-376.md Adds a Link Wizard handoff doc (appears unrelated to this PR’s scope).
Review details

Suppressed comments (1)

src/components/Admin/ScheduleImport/TypedSetsPanel.tsx:71

  • Using <typeLabel.icon /> is inconsistent with the established pattern elsewhere in the codebase (e.g. src/components/SetTypePlaceholder.tsx:15-25 destructures icon into Icon and renders <Icon />). Switching to the same pattern improves readability and avoids any JSX member-expression edge cases.
function SetTypeChip({ setType }: { setType: string | null }) {
  const typeLabel = getSetTypeLabel(setType);
  return (
    <Badge variant="secondary" className="gap-1 shrink-0">
      <typeLabel.icon className={`h-3 w-3 ${typeLabel.color}`} />
  • Files reviewed: 18/18 changed files
  • Comments generated: 5
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/handoffs/link-wizard-376.md Outdated
Comment thread supabase/functions/diff-schedule/types.ts
Comment thread supabase/functions/diff-schedule/types.ts
Comment thread src/services/scheduleImport/types.ts
Comment thread src/components/Admin/ScheduleImport/TypedSetsPanel.tsx
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown

Playwright test results

passed  62 passed

Details

stats  62 tests across 20 suites
duration  1 minute, 28 seconds
commit  d7222c3

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.

🟡 Changes recommended

Artist-less matching can select the wrong dated set, ignored rows can fail type validation, and an unrelated handoff is included.

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

Review details

Suppressed comments (1)

docs/handoffs/link-wizard-376.md:5

  • This handoff documents issue #376's Link Wizard work and is unrelated to this PR's #433 schedule-import scope. It also contains stale branch, path, and session instructions; remove this file from the PR.
# Handoff: Link Wizard Enhancements (Issue #376)

## Focus for next session

Run the `prototype` skill to settle the one open structural question (Q13 below: desktop layout with artist list moved to the left side), then continue/finish the `grilling` design session and move into `domain-modeling` if needed. This is a **continuation of an in-progress `/grill-with-docs 376` session** — the grilling interview is functionally done (all decisions settled except the prototype), do not restart it from scratch.
  • Files reviewed: 18/18 changed files
  • Comments generated: 3
  • Review effort level: Balanced

Comment thread src/services/scheduleImport/parseCsv.ts Outdated
Comment thread supabase/functions/diff-schedule/computeDiff.ts Outdated
Comment thread src/components/Admin/ScheduleImport/TypedSetsPanel.tsx Outdated
Drop the unrelated link-wizard handoff doc, validate the Type column
only on rows the import keeps, narrow set-matching by stage and date
together so same-name artist-less sets on different dates update the
right row, and type setType/previousSetType as SetType | null across
the diff contract.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TL2F1n6R7dmSfQiMbornRG

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.

🟡 Changes recommended

Artist-less matching can select and update the wrong existing set when date or stage discriminators do not resolve exactly.

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

Review details

Suppressed comments (1)

supabase/functions/diff-schedule/computeDiff.ts:47

  • Artist-less identity now depends on stage, but stage mismatches reach findMatchingSet with a null id (applyStageResolution returns null for mismatches). If two zero-artist sets share a name/date on different stages, a CSV value such as Mainstage can therefore select an arbitrary set before the user maps it to Main Stage; the later commit-payload mapping only changes stageName and cannot correct the chosen set id. Stage-sensitive matching must incorporate the user's mismatch resolution (or defer selecting the set until that resolution is known).
      row.artists.length === 0
        ? (indexes.artistlessSetsByNameLower.get(name.toLowerCase()) ?? [])
        : (indexes.setsByArtistKey.get(artistKey(artistSlugs)) ?? []);
  • Files reviewed: 17/17 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread supabase/functions/diff-schedule/resolvers.ts Outdated
An artist-less row's supplied date or stage now excludes stored sets that
contradict it, so a same-name set on another day becomes a create instead
of overwriting the wrong set. Roster-based matching keeps its fuzzy
narrowing; stored sets without a time or stage still match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TL2F1n6R7dmSfQiMbornRG
Function- and type-level explanations become JSDoc so they surface on
hover; the collectNewArtists comment restated its name and is removed.
Mid-function constraint notes stay as line comments.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TL2F1n6R7dmSfQiMbornRG
The panel only reads setsToCreate/setsToUpdate, so it takes those
instead of the whole diff result.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TL2F1n6R7dmSfQiMbornRG
Comments that predate this branch go back to line comments (and the
removed collectNewArtists one returns), so the PR diff only touches
comments it introduced.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TL2F1n6R7dmSfQiMbornRG
…urpose-first resolver docs

computeDiff.test.ts had grown past 700 lines; the artist-less matching
tests now live in computeDiff.artistless.test.ts with shared fixtures in
fixtures.ts. Resolver JSDoc rewritten to state what each function is for
rather than how it works.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TL2F1n6R7dmSfQiMbornRG

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.

🟡 Changes recommended

Unresolved fuzzy-stage selection can update the wrong artist-less set after the reviewer chooses a different stage resolution.

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

Review details

Suppressed comments (2)

Previously missed (1) — in code that hasn't changed since the last review.

CONTEXT.md:44

  • CONTEXT.md is the domain glossary, but these definitions embed the schedule-import matching algorithm and duplicate ADR-0008. Keeping implementation rules here makes the glossary definitions long and creates another source that can drift; leave the terms domain-only and keep matching behavior in the ADR/import documentation.
The artists on a single **set** — one, or several for a B2B. Per-set, where **lineup** is per-edition. A set's roster is its import identity: schedule re-imports match a roster set by its artists (order-insensitive), not by its name. See ADR-0008.
_Avoid_: Lineup (that's the whole edition), billing

**Artist-less set**:
A **set** with an empty **roster** (e.g. a fire show or an unhosted workshop). Its import identity is its name plus date/stage, unlike a roster set, which is identified by its artists — so adding an artist to a set changes how re-imports match it. See ADR-0008.

supabase/functions/diff-schedule/resolvers.ts:162

  • Artist-less matching selects a set using the fuzzy match's closest stage before the user resolves that mismatch. If the reviewer maps the CSV stage to another existing stage—or chooses to create it—the commit still updates the set chosen for the closest stage and only rewrites stageName, so the wrong set can be moved/overwritten while the intended set remains orphaned. Defer artist-less selection until the stage resolution is known, or carry enough candidate information to recompute the match from the chosen resolution.
  const stageSupplied = context.stage.kind !== "none";
  const stageId = provisionalStageId(context.stage);
  const pool = candidates.filter((s) => {
  • Files reviewed: 23/23 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread docs/adr/0008-artist-less-set-matching.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Playwright test results

failed  3 failed
passed  335 passed

Details

stats  338 tests across 24 suites
duration  8 minutes, 4 seconds
commit  14032a7

Failed tests

Mobile Chrome › set-form-type.spec.ts › Admin set form: set types › creates a workshop with no artists via the form
Mobile Chrome › set-type-filter.spec.ts › Set type filter › filtering to workshops leaves only workshop sets
Mobile Safari › set-type-filter.spec.ts › Set type filter › filtering to workshops leaves only workshop sets

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Schedule import: type column and artist-less rows

3 participants