Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
5134 commits
Select commit Hold shift + click to select a range
6c31515
refactor: remove redundant DialogProvider nesting
jthrilly Apr 23, 2026
d59c6a2
refactor: address PR review feedback
jthrilly Apr 23, 2026
fa04ee2
fix(interviewer): restore interview-scoped DialogProvider
jthrilly Apr 23, 2026
dcd9f78
use UUIDv4 for mapbox search session token
buckhalt Apr 24, 2026
2f4365d
refactor(mapbox-token): rotate mapbox search token after each retriev…
buckhalt Apr 27, 2026
c5372f9
build(deps): bump uuid from 13.0.0 to 14.0.0
dependabot[bot] Apr 27, 2026
4003405
build(deps): bump @prisma/adapter-neon from 7.7.0 to 7.8.0
dependabot[bot] Apr 27, 2026
f630ff5
build(deps): bump @aws-sdk/s3-request-presigner
dependabot[bot] Apr 27, 2026
d0bbd43
build(deps-dev): bump knip from 6.5.0 to 6.7.0
dependabot[bot] Apr 27, 2026
fb0b2be
build(deps): bump mapbox-gl from 3.21.0 to 3.22.0
dependabot[bot] Apr 27, 2026
c6c0fe1
fix(mapbox-token): cancel pending debounced fetch on reset paths
buckhalt Apr 27, 2026
428a357
refactor(interviewer): address code review feedback
jthrilly Apr 29, 2026
b0ef5fc
Merge pull request #730 from complexdatacollective/dependabot/npm_and…
jthrilly Apr 29, 2026
9ed7574
Merge pull request #729 from complexdatacollective/dependabot/npm_and…
jthrilly Apr 29, 2026
20e66ff
Merge pull request #728 from complexdatacollective/dependabot/npm_and…
jthrilly Apr 29, 2026
57602a9
Merge pull request #727 from complexdatacollective/dependabot/npm_and…
jthrilly Apr 29, 2026
af21f29
Merge pull request #726 from complexdatacollective/dependabot/npm_and…
jthrilly Apr 29, 2026
ce50372
fix(mapbox-token): lazy init session token, fix stale debounce cleanu…
Copilot Apr 29, 2026
57b0e35
refactor: co-locate pedigree-layout with FamilyPedigree stage
jthrilly Apr 29, 2026
b535544
feat(setup-database): scaffold migrateProtocolsToV8 with no-op test
jthrilly Apr 29, 2026
a918a52
docs(setup-database): clarify Asset rows are orphaned, not cascaded
jthrilly Apr 29, 2026
9196e3c
test(setup-database): pin orphan asset cleanup ordering
jthrilly Apr 29, 2026
d431ed7
test(setup-database): symmetric non-null assertion on call order indices
jthrilly Apr 29, 2026
212037c
feat(setup-database): delete orphan UploadThing blobs during cleanup
jthrilly Apr 29, 2026
09934c0
refactor(setup-database): type STORAGE_SETTING_KEYS as AppSetting[]
jthrilly Apr 29, 2026
af373fd
feat(setup-database): support S3 provider for orphan blob cleanup
jthrilly Apr 29, 2026
b28bf2e
Merge pull request #724 from complexdatacollective/refactor/mapbox-se…
jthrilly Apr 29, 2026
9e8b6e2
test(setup-database): pin best-effort behavior on blob cleanup failure
jthrilly Apr 29, 2026
05e33b1
feat(setup-database): migrate v7 Protocol rows to v8 in place
jthrilly Apr 29, 2026
b1d7c13
chore: fix typecheck, knip, and lint
jthrilly Apr 29, 2026
de55ad4
fix(setup-database): include lastModified in v7→v8 reconstruction for…
jthrilly Apr 29, 2026
bbc82f3
delete unused files
jthrilly Apr 29, 2026
52587ad
test(setup-database): pin hash equality with import flow
jthrilly Apr 29, 2026
5431b88
feat(setup-database): wrap migration errors with protocol id and name
jthrilly Apr 29, 2026
32fee16
feat(setup-database): wrap P2002 hash collision with both protocol co…
jthrilly Apr 29, 2026
6d0c974
feat(setup-database): run migrateProtocolsToV8 after prisma migrate d…
jthrilly Apr 29, 2026
4f0bc23
refactor: move getEntityAttributes out of network-exporters package
jthrilly Apr 29, 2026
4987e86
refactor: move externalData out of network-exporters package
jthrilly Apr 29, 2026
b05cf99
refactor(protocol): hash on codebook+stages only for stable identity
jthrilly Apr 29, 2026
d95bc2e
refactor(setup-database): tighten error handling in deleteOrphanBlobs
jthrilly Apr 29, 2026
71128b8
Merge remote-tracking branch 'origin/next' into refactor/interviewer-…
jthrilly Apr 29, 2026
334f2d2
refactor: move session helpers up one level (formatters/session → ses…
jthrilly Apr 29, 2026
59721f4
refactor: move lib/export contents into lib/network-exporters
jthrilly Apr 29, 2026
c6c3e7c
refactor: move host-side export layers out of network-exporters package
jthrilly Apr 29, 2026
0811f0c
refactor: split network-exporters/utils/types into options, input, ou…
jthrilly Apr 29, 2026
091e7d1
refactor: typed export errors with class-based classification
jthrilly Apr 29, 2026
32b940d
refactor: move SSE wire format from package to route handler
jthrilly Apr 29, 2026
3726d7f
refactor: package-owned FileStorage tag with Readable upload signature
jthrilly Apr 29, 2026
e151229
feat: streaming upload for export archive (Readable end-to-end)
jthrilly Apr 29, 2026
26fa231
refactor(db): consolidate PreviewProtocol into Protocol with isPrevie…
jthrilly Apr 29, 2026
63c76b7
refactor: typed csvShared.ts and mockObjects.ts
jthrilly Apr 29, 2026
3a426dc
refactor: package owns InterviewExportInput; PrismaInterviewRepositor…
jthrilly Apr 29, 2026
151a6f6
fix: use path aliases in mockObjects.ts imports
jthrilly Apr 29, 2026
da27af5
feat: typed attributeListRows generator alongside legacy class
jthrilly Apr 29, 2026
21095ef
feat: typed edgeListRows generator alongside legacy class
jthrilly Apr 29, 2026
21e8d80
feat: typed egoListRows generator alongside legacy class
jthrilly Apr 29, 2026
ebdca29
feat: typed adjacencyMatrixRows generator alongside legacy class
jthrilly Apr 29, 2026
a7bebf6
feat(db): explicit migration for preview-into-protocol consolidation
jthrilly Apr 29, 2026
c4a57ef
Revert "feat(db): explicit migration for preview-into-protocol consol…
jthrilly Apr 29, 2026
bfb1388
feat: switch CSV formatter dispatch to typed Readable factories; dele…
jthrilly Apr 29, 2026
e7c453e
Merge pull request #722 from complexdatacollective/refactor/interview…
jthrilly Apr 29, 2026
91f1c2d
feat: streaming upload, ensure cleanup, partial-success ExportReturn
jthrilly Apr 29, 2026
6145a67
refactor: host consumers consume new ExportReturn shape
jthrilly Apr 29, 2026
357c994
fix(signup): allow show/hide toggle on confirm password field
buckhalt Apr 29, 2026
f2c58fc
test: implement partial-success pipeline test via formatter mock
jthrilly Apr 29, 2026
c958e51
Merge origin/next into network-exporters refactor
jthrilly Apr 29, 2026
e6f10e0
disallow type prop for PasswordField component
buckhalt Apr 29, 2026
afcedb5
chore(dev): swap local S3 image from Robothy to MinIO
jthrilly Apr 29, 2026
78c3693
fix(storage): use path-style URLs for S3 public asset URLs
jthrilly Apr 29, 2026
9290a6d
fix(synthetic-interviews): emit schema-valid stageMetadata
jthrilly Apr 29, 2026
a0abcdc
fix(dashboard): use Trash2 icon for protocol delete action
jthrilly Apr 29, 2026
9bae070
chore: drop unused exports flagged by knip
jthrilly Apr 29, 2026
82366b6
feature(protocols): allow downloading original .netcanvas protocol
buckhalt Apr 29, 2026
b729335
refactor(protocols): use useDownload hook for download action
buckhalt Apr 29, 2026
cbc997b
refactor(protocols): unify asset and original file upload into one call
buckhalt Apr 29, 2026
ade5aba
reorganise UI components ready for migration to package
jthrilly Apr 29, 2026
5528937
Merge pull request #731 from complexdatacollective/fix/confirm-passwo…
jthrilly Apr 29, 2026
56bb573
Merge remote-tracking branch 'origin/next' into feature/download-prot…
buckhalt Apr 29, 2026
a7f8865
refactor(protocols): verify uploaded original file matches input by name
buckhalt Apr 29, 2026
b680504
Merge pull request #732 from complexdatacollective/feature/download-p…
jthrilly Apr 30, 2026
0069316
fix(dashboard): preserve activity filter search and unify login events
claude Apr 30, 2026
eca1805
fix(dashboard): keep Recovery Code Used as a distinct activity type
claude Apr 30, 2026
98b3431
Fix: preserve badge colors for legacy activity types with default fal…
Copilot Apr 30, 2026
4c51ba8
Merge pull request #733 from complexdatacollective/claude/fix-activit…
jthrilly Apr 30, 2026
3ebe646
fix(combobox): keep search query when an item is selected
claude Apr 30, 2026
7e5b22c
docs(combobox): note base-ui workaround and upstream tracking issues
claude Apr 30, 2026
318e880
feat(deps): add @codaco/fresco-ui@next
jthrilly Apr 30, 2026
7b77384
feat(fresco): import @codaco/fresco-ui/styles.css and bump tailwindcss
jthrilly Apr 30, 2026
fe636d3
fix(ci): set Netlify DB env before deploy and force a fresh build
claude Apr 30, 2026
b581091
refactor(fresco): relocate SubmitButton, Link (drop NativeLink export…
jthrilly Apr 30, 2026
2ce02db
refactor(fresco): rewrite imports to @codaco/fresco-ui
jthrilly Apr 30, 2026
54e9282
fix(ci): skip Netlify auto-builds without branch-scoped DB env
claude Apr 30, 2026
582bc8a
chore(deps): bump @codaco/fresco-ui to 0.1.0-next.1
jthrilly Apr 30, 2026
77ee71c
fix(useProtocolForm): rewrite relative imports to @codaco/fresco-ui a…
jthrilly Apr 30, 2026
ef7867e
test(e2e): skip geospatial stage on WebKit too
claude Apr 30, 2026
7632ea4
Merge pull request #734 from complexdatacollective/claude/preserve-co…
jthrilly Apr 30, 2026
6da2d29
chore(fresco): delete code migrated to @codaco/fresco-ui and clean un…
jthrilly Apr 30, 2026
e8ad96e
chore(deps): bump @codaco/fresco-ui to 0.1.0-next.2
jthrilly May 1, 2026
fb6239c
fix(geospatial): re-enable mapbox-gl/dist/mapbox-gl.css import (WebKi…
jthrilly May 1, 2026
4c01781
Merge remote-tracking branch 'origin/next' into reorganise-ui
jthrilly May 1, 2026
e0ff651
Revert "fix(geospatial): re-enable mapbox-gl/dist/mapbox-gl.css impor…
jthrilly May 1, 2026
745aa59
chore(deps): bump @codaco/fresco-ui to ^0.1.0 stable
jthrilly May 1, 2026
d9149ab
chore(deps+test): bump @codaco/fresco-ui to 0.1.1; drop stale webkit …
jthrilly May 1, 2026
5d58a78
test(e2e): remove stale webkit geospatial snapshots
jthrilly May 1, 2026
2091c22
refactor: update fresco-ui form import paths after flatten
jthrilly May 1, 2026
7f8060b
refactor: update fresco-ui imports for renamed components
jthrilly May 1, 2026
23a27a7
chore: drop unused dateOptions export flagged by knip
jthrilly May 1, 2026
d85bee0
chore(deps): bump @codaco/fresco-ui to ^0.2.1
jthrilly May 1, 2026
4b7c0ff
chore(deps): add @codaco/tailwind-config as direct dep
jthrilly May 1, 2026
e35163b
chore(deps): bump @codaco/fresco-ui to ^0.3.0; hoist tailwind-config …
jthrilly May 1, 2026
77103a0
test(e2e): skip geospatial stages 19, 40, 50 on webkit
jthrilly May 1, 2026
48cfce5
chore(deps): bump @codaco/fresco-ui to ^1.0.0
jthrilly May 1, 2026
43be1b4
chore(deps): bump @codaco/fresco-ui to ^2.0.0; pin tailwind-config
jthrilly May 1, 2026
437028e
refactor: import canonical themes from @codaco/tailwind-config
jthrilly May 1, 2026
1120daa
chore(fresco-ui-dep): bump @codaco/fresco-ui to ^2.0.1; drop now-redu…
buckhalt May 1, 2026
a4c38ac
Merge pull request #735 from complexdatacollective/reorganise-ui
buckhalt May 1, 2026
5b4ad70
feat(geospatial): add UA detection for Mapbox stub mode
jthrilly May 4, 2026
b34ecb7
feat(geospatial): add GeospatialStubSearch component for E2E
jthrilly May 4, 2026
17e3f30
feat(geospatial): wire E2E stub render path on webkit/firefox
jthrilly May 4, 2026
10c762e
fix(geospatial): remove type assertion and redundant stub guards
jthrilly May 4, 2026
5526709
test(e2e): stub-mode short-circuits in geospatial fixture waits
jthrilly May 4, 2026
42a9af1
test(e2e): remove webkit/firefox skips on geospatial stages
jthrilly May 4, 2026
2fb4712
test(e2e): regenerate visual snapshot baselines for geospatial stub
jthrilly May 4, 2026
bf3c7ee
use network-query package
jthrilly May 4, 2026
756fc62
perf(geospatial): dynamic-import GeospatialStubSearch to keep it out …
jthrilly May 4, 2026
309fdc2
chore(deps): add @codaco/network-exporters ^1.0.1
jthrilly May 4, 2026
decaa38
feat(export): add describeExportError for new package error tags
jthrilly May 4, 2026
9796a33
chore(deps): bump @codaco/network-exporters to ^1.0.2; drop ambient s…
jthrilly May 4, 2026
9f19558
refactor(export): drop type assertion in classifyCause
jthrilly May 4, 2026
99ded53
feat(export): move ExportSseEvent + formatSSE to lib/export/sseEvents
jthrilly May 4, 2026
11344a6
feat(export): add Prisma-backed InterviewRepository layer
jthrilly May 4, 2026
7646c53
feat(export): add Prisma-backed ProtocolRepository layer
jthrilly May 4, 2026
aa96031
feat(export): add makeS3Sink for streaming zip uploads
jthrilly May 4, 2026
80529d3
feat(export): add makeUploadThingSink for streaming zip uploads
jthrilly May 4, 2026
f1d698a
feat(export): add makeLocalSink for streaming zip uploads
jthrilly May 4, 2026
460c2bd
feat(export): add Output layer factories for s3/uploadthing/local
jthrilly May 4, 2026
b530e8c
fix(export): stabilize Output integration tests
jthrilly May 4, 2026
020ebb5
refactor(export): rewire export route to @codaco/network-exporters
jthrilly May 4, 2026
d684abf
refactor(export): switch consumers to @codaco/network-exporters
jthrilly May 4, 2026
4d1f7ff
refactor(storage): drop network-exporters bundling from storage layers
jthrilly May 4, 2026
849ca1c
refactor(export): remove local network-exporters lib and orphaned layers
jthrilly May 4, 2026
2cb1887
fix(quick-add): lucide icon rendering in node action buttons
buckhalt May 4, 2026
ab98ef8
chore(stories): add lucide icon types to node action button story con…
buckhalt May 4, 2026
659e592
chore(stories): remove non-node-type icons from action button options
buckhalt May 4, 2026
8129878
fix(action-button-variants): restore custom icon sizing in node actio…
buckhalt May 4, 2026
c3d86b9
chore: drop redundant size prop on plus icons
buckhalt May 4, 2026
c4536d5
build(deps-dev): bump eslint-plugin-better-tailwindcss
dependabot[bot] May 4, 2026
eec9b11
build(deps): bump @prisma/adapter-pg from 7.7.0 to 7.8.0
dependabot[bot] May 4, 2026
d55f424
build(deps): bump posthog-js from 1.367.0 to 1.372.8
dependabot[bot] May 4, 2026
8987468
build(deps): bump es-toolkit from 1.45.1 to 1.46.1
dependabot[bot] May 4, 2026
5342cdf
chore(deps): remove unused archiver/xmldom/sanitize-filename
jthrilly May 4, 2026
2c83881
fix(stories): pin interview theme on QuickAddField and NodeForm stories
buckhalt May 4, 2026
4ef7730
refactor: replace lib/interviewer with @codaco/interview package
jthrilly May 5, 2026
44338b9
chore: remove orphaned CopyDebugInfoButton
jthrilly May 5, 2026
d56f37f
chore: remove playwright and all e2e test infrastructure
jthrilly May 5, 2026
756b3a2
chore: remove E2E_TEST runtime branches and orphaned support code
jthrilly May 5, 2026
3ebb812
Merge pull request #742 from complexdatacollective/dependabot/npm_and…
jthrilly May 5, 2026
86cc27c
Merge pull request #741 from complexdatacollective/dependabot/npm_and…
jthrilly May 5, 2026
77a5696
Merge pull request #740 from complexdatacollective/dependabot/npm_and…
jthrilly May 5, 2026
9b1f9d4
Merge pull request #738 from complexdatacollective/dependabot/npm_and…
jthrilly May 5, 2026
13d2f93
Merge pull request #737 from complexdatacollective/fix/quickadd-lucid…
jthrilly May 5, 2026
f2f49f8
build(deps): bump @prisma/client from 7.7.0 to 7.8.0
dependabot[bot] May 5, 2026
3c1ec2f
chore(deps): bump @codaco/interview to 1.0.0-alpha.1
jthrilly May 5, 2026
8ea254e
chore: merge next into interview-package (branch wins on conflict)
jthrilly May 5, 2026
b74107e
fix(deps): bump @base-ui/react to ^1.4.1 with pnpm override to dedupe
jthrilly May 5, 2026
1cf2812
chore(deps): bump @codaco/fresco-ui to ^2.1.0; drop @base-ui/react ov…
jthrilly May 5, 2026
5a277c1
chore(deps): bump @codaco/tailwind-config to ^0.4.1
jthrilly May 5, 2026
2732e99
chore(deps): bump tailwind-config 0.5.0 + fresco-ui 2.2.0; switch to …
jthrilly May 5, 2026
f06818b
chore(deps): bump @codaco/{tailwind-config,fresco-ui,interview} to tr…
jthrilly May 5, 2026
d80821b
remove duplicated utilities
jthrilly May 5, 2026
e9bced1
chore(deps): bump @codaco/tailwind-config to 1.0.0-alpha.1
jthrilly May 5, 2026
607111b
chore(deps): bump @codaco/{tailwind-config,fresco-ui} to track varian…
jthrilly May 5, 2026
07103da
feat: integrate @codaco/interview@1.0.0-alpha.4 analytics
jthrilly May 5, 2026
dc893f5
chore(deps): bump @codaco/tailwind-config to 1.0.0-alpha.4
jthrilly May 5, 2026
82640df
chore(deps): bump @codaco/interview to 1.0.0-alpha.5
jthrilly May 5, 2026
8b56366
chore(deps): bump @codaco/tailwind-config to 1.0.0-alpha.5
jthrilly May 5, 2026
9ac2b87
Merge pull request #739 from complexdatacollective/dependabot/npm_and…
jthrilly May 5, 2026
465b94e
chore(deps): bump @codaco/{interview,tailwind-config} to 1.0.0-alpha.6
jthrilly May 5, 2026
763e8f5
chore(deps): bump @codaco/{interview,tailwind-config} to 1.0.0-alpha.7
jthrilly May 5, 2026
48ecb56
chore(deps): bump @codaco/fresco-ui to 2.5.2
jthrilly May 5, 2026
7816e8d
chore(deps): bump @codaco/{interview,tailwind-config} to 1.0.0-alpha.8
jthrilly May 5, 2026
649b6a5
fix(storybook): drop stale theme imports; rename data-theme attribute
jthrilly May 5, 2026
4105cb6
Merge branch 'next' into interview-package
jthrilly May 5, 2026
15669cb
fix(test): eliminate flaky timeout in Output.test.ts s3 happy path
jthrilly May 5, 2026
7b139dd
chore(deps): bump @codaco/interview to 1.0.0-alpha.9
jthrilly May 5, 2026
cbebeda
chore(deps): bump @codaco/{tailwind-config,fresco-ui,interview}
jthrilly May 5, 2026
c42a682
fix(globals.css): drop duplicate @import "tailwindcss"
jthrilly May 5, 2026
680367a
chore(deps): bump @codaco/{fresco-ui,interview,tailwind-config}
jthrilly May 7, 2026
3076886
bump package
jthrilly May 7, 2026
08028b9
chore(deps): bump @codaco/interview to 1.0.0-alpha.13
jthrilly May 7, 2026
ddd61df
fix(interview): push step changes to browser history
jthrilly May 7, 2026
b0b03aa
feat(protocols-table): default sort by import date, newest first
jthrilly May 7, 2026
f934032
remove --color prefixed variables in preparation for theming change
jthrilly May 8, 2026
9e3a48a
chore(deps): bump @codaco/{interview,fresco-ui} to alpha.17 / 2.9.0
jthrilly May 8, 2026
419afbc
ci: pin setup-pnpm, chromaui, and setup-bun to immutable SHAs
jthrilly May 12, 2026
284074d
ci: bump first-party actions to latest major versions
jthrilly May 12, 2026
477ff2c
ci: SHA-pin deploy-preview actions and migrate to thollander v3
jthrilly May 12, 2026
ab2c0a1
ci(chromatic): harden issue_comment trigger against fork-PR abuse
jthrilly May 12, 2026
19bf35a
ci: bump e2e workflow actions to latest major versions
jthrilly May 12, 2026
357e80d
ci(e2e): scope id-token: write to jobs that consume it
jthrilly May 12, 2026
7c26899
Merge pull request #750 from complexdatacollective/ci-supply-chain-ha…
jthrilly May 12, 2026
2f529fe
remove arbitrary values
jthrilly May 12, 2026
ee8ddec
chore(deps): bump @codaco/{fresco-ui,interview,tailwind-config} to 2.…
jthrilly May 12, 2026
607fe09
Merge remote-tracking branch 'origin/next' into interview-package
jthrilly May 12, 2026
59340a7
fix(data-table): wrap --sea-green tuple in oklch() for color-mix
jthrilly May 12, 2026
d5d290c
same size text in exported inteterview column
jthrilly May 12, 2026
d46a1b9
chore(deps): bump @codaco/{fresco-ui,interview,tailwind-config} to 2.…
jthrilly May 12, 2026
49caee3
feat: remove Preview Mode feature
jthrilly May 13, 2026
1514659
Merge pull request #751 from complexdatacollective/remove-preview-mode
jthrilly May 13, 2026
ffc31a5
Merge pull request #743 from complexdatacollective/interview-package
jthrilly May 13, 2026
e932c2c
chore(deps): bump @codaco/interview to 1.0.0-alpha.20
jthrilly May 14, 2026
d149f11
feat(api): add protocols-meta endpoint
buckhalt May 14, 2026
c975393
refactor(api): address coderabbit review
buckhalt May 14, 2026
6a9dc49
chore(deps): update all dependencies to latest
claude May 14, 2026
77c922b
chore(deps): pin @types/node to v24 to match project config
claude May 14, 2026
b6db856
fix(RecruitmentTestSection): drop as Route casts flagged by lint in CI
claude May 14, 2026
ca4ff60
fix(RecruitmentTestSection): use Route annotation without redundant c…
claude May 14, 2026
6776317
chore: run next typegen on postinstall so Route is narrowed for CI
claude May 14, 2026
5bc8120
Merge pull request #753 from complexdatacollective/claude/update-all-…
jthrilly May 14, 2026
61fd9e1
chore: upgrade pnpm to v11
claude May 15, 2026
1331c44
chore: pin pnpm packageManager hash, document exact version
claude May 15, 2026
434ae20
Merge pull request #755 from complexdatacollective/claude/upgrade-pnp…
jthrilly May 15, 2026
f345263
refactor(posthog): make server telemetry helpers non-throwing
jthrilly May 15, 2026
b1a50f2
ci: install netlify-cli via npm to avoid pnpm 10 global bin issue
jthrilly May 15, 2026
8bc4f12
ci: bump shared setup-pnpm action to v2
jthrilly May 15, 2026
8b36f75
Merge pull request #752 from complexdatacollective/feature/api-protoc…
jthrilly May 15, 2026
706ce2c
ci: use mode: delete for failure-comment cleanup
jthrilly May 15, 2026
3d60131
ci: gate deploy preview on Netlify build outcome, add prod deploy on …
jthrilly May 15, 2026
6e20e42
ci: drop production deploy workflow — Netlify handles pushes to next
jthrilly May 15, 2026
08f3d53
ci: add Production Deploy Status check for pushes to next
jthrilly May 15, 2026
dbabade
chore(deps): update @codaco packages, move DataTable to fresco-ui
jthrilly May 21, 2026
51633fa
fix(activity-feed): let Details cells wrap so the table stops overflo…
jthrilly May 21, 2026
a5f5d6e
build(deps-dev): bump fflate from 0.8.2 to 0.8.3
dependabot[bot] May 21, 2026
302e569
build(deps-dev): bump tsx from 4.22.0 to 4.22.3
dependabot[bot] May 21, 2026
4253a0c
Merge pull request #761 from complexdatacollective/dependabot/npm_and…
jthrilly May 27, 2026
a53223e
Merge pull request #760 from complexdatacollective/dependabot/npm_and…
jthrilly May 27, 2026
5b6a1b8
build(deps): update dependencies to latest versions
jthrilly Jun 1, 2026
49b3fc0
build(deps): update @codaco packages to latest versions
jthrilly Jun 1, 2026
c7b99eb
feat(activity-feed): attribute admin events to user and add CSV export
jthrilly Jun 2, 2026
ae6b2ba
feat(import): add protocol upload size limit helper
jthrilly Jun 3, 2026
1e3aef7
feat(import): add dedicated uploading-protocol progress phase
jthrilly Jun 3, 2026
3ebe8fa
feat(uploadthing): add createUpload export and retry wrapper
jthrilly Jun 3, 2026
ddfecc8
refactor(import): route uploadthing uploads through retry wrapper
jthrilly Jun 3, 2026
ab7e575
feat(import): upload protocol file in its own step before assets
jthrilly Jun 3, 2026
0a514fa
feat(import): guard oversized protocols and show spinner toast icon
jthrilly Jun 3, 2026
937e357
feat(import): show upload protocol phase and numeric percentage
jthrilly Jun 3, 2026
f5694d6
test(import): add uploading-protocol story and update percentages
jthrilly Jun 3, 2026
4a86656
feat(import): clean up orphaned uploads when an import fails
jthrilly Jun 3, 2026
a504d06
fix(import): inclusive size-limit wording and round file size up
jthrilly Jun 3, 2026
057be82
Merge pull request #771 from complexdatacollective/fix/large-protocol…
jthrilly Jun 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
335 changes: 335 additions & 0 deletions .claude/skills/generate-e2e-tests/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
---
name: generate-e2e-tests
description: Generate comprehensive Playwright e2e tests from a .netcanvas protocol file and an optional recording. Invoke with /generate-e2e-tests <protocol-path> [recording-path]
user-invocable: true
---

# Generate E2E Tests from Protocol

You are generating comprehensive Playwright e2e tests for a Fresco interview protocol.

## Inputs

- **Protocol path**: `$1` — path to a `.netcanvas` file (ZIP containing `protocol.json`)
- **Recording path** (optional): `$2` — path to a recording directory (contains `actions.jsonl`, `SESSION.md`, `screenshots/`)

If no recording is provided, generate a **synthetic happy path** using the data generation strategies in STAGE_TEST_REFERENCE.md (see "Synthetic Data Generation" section).

## Step 1: Read Reference Materials

Read these files to understand the testing infrastructure and patterns:

1. `tests/e2e/docs/STAGE_TEST_REFERENCE.md` — what to test for each stage type, fixture availability, validation testing patterns
2. `tests/e2e/fixtures/stage-fixture.ts` — available fixture methods and their signatures
3. `tests/e2e/fixtures/interview-fixture.ts` — interview navigation fixture
4. `tests/e2e/fixtures/protocol-fixture.ts` — protocol installation and network state inspection
5. `tests/e2e/CLAUDE.md` — full e2e testing architecture guide
6. `tests/e2e/specs/interview/silos-protocol.spec.ts` — reference test implementation to match style/structure
7. `CLAUDE.md` — project coding conventions (path aliases, TypeScript, etc.)

## Step 2: Extract and Analyze Protocol

Extract the protocol JSON:

```bash
unzip -p "$1" protocol.json
```

From the extracted JSON, build a **stage map** — for each stage (by index), extract:

- `type` — stage type (e.g., `NameGeneratorQuickAdd`, `EgoForm`, `Sociogram`)
- `label` — display label
- `subject` — `{ entity, type }` pointing to codebook entry (null for Information/Anonymisation)
- `introductionPanel` — title and text (if present)
- `form.fields[]` — array of `{ variable }` referencing codebook variables
- `prompts[]` — array of prompt objects (with `createEdge`, `variable`, `highlight`, etc.)
- `panels[]` — side panel configuration
- `behaviours` — `maxNodes`, `minNodes`, `freeDraw`, etc.

For each form field, resolve the variable UUID against the codebook:

- Look up `codebook.[entity].[type].variables.[variableId]`
- Extract: `name`, `type`, `component`, `validation`, `options`

This gives you the field name (UUID), display name, input component type, validation rules, and available options for each form field.

## Step 3: Analyze Recording (if provided)

If `$2` is provided, read `$2/actions.jsonl` (one JSON object per line).

Group actions by stage — track URL changes via the `step=N` query parameter. For each stage visited:

- Extract the sequence of user actions (click, fill, press, select)
- Note filled values and selected options
- Note which nodes were created (names entered in quick-add or name generator forms)
- Note edge-creating interactions (sociogram clicks, dyad census selections)

The recording represents the **happy path** — the exact user journey to replay.

### If no recording

Generate a synthetic happy path from the protocol alone:

1. Walk through all stages in order (index 0 to N)
2. For each stage, use the **Synthetic Data Generation** section of STAGE_TEST_REFERENCE.md to determine what values to fill, how many nodes to create, etc.
3. For conditional/skip logic, choose the path that visits the **most stages**
4. Track synthetic state as you go — node names created on earlier stages are needed for bin/census/sociogram stages later

## Step 4: Generate Test File

Create `tests/e2e/specs/interview/<protocol-name>.spec.ts` where `<protocol-name>` is derived from the protocol name (kebab-case, lowercase).

### File Structure

Follow this exact pattern (from the reference implementation):

```typescript
/**
* <Protocol Name> Tests
*
* Tests interview stage navigation using a real .netcanvas protocol file.
*/

import path from 'node:path';
import { expect, test } from '~/tests/e2e/fixtures/interview-test.js';
import { expectURL } from '~/tests/e2e/helpers/expectations.js';

const PROTOCOL_PATH = path.resolve(
import.meta.dirname,
'../../data/<filename>.netcanvas',
);

let sharedProtocolId: string;

test.describe('<Protocol Name>', () => {
test.beforeAll(async ({ database, protocol }) => {
await database.restoreSnapshot();
const { protocolId } = await protocol.install(PROTOCOL_PATH);
sharedProtocolId = protocolId;
});

test.describe('Happy Path', () => {
test.describe.configure({ mode: 'serial' });

let interviewId: string;

test.beforeAll(async ({ protocol }) => {
interviewId = await protocol.createInterview(sharedProtocolId);
});

test.beforeEach(({ interview }) => {
interview.interviewId = interviewId;
});

test.afterEach(async ({ page, interview }) => {
const stepMatch = /step=(\d+)/.exec(page.url());
if (stepMatch?.[1]) {
const step = stepMatch[1];
// List stage indices with non-deterministic rendering
const highToleranceStages: string[] = [/* sociogram indices */];

await interview.capture(`stage-${step}-final`, {
maxDiffPixelRatio: highToleranceStages.includes(step)
? 0.1
: undefined,
});
}
});

// One test() per stage...
});
});
```

### Per-Stage Test Generation

For each stage in the protocol, generate a `test()` block. Use the STAGE_TEST_REFERENCE.md to determine what to test.

#### Mapping Recording Actions to Fixture Calls

Translate recording actions to fixture method calls using these mappings:

| Recording Pattern | Fixture Call |
|---|---|
| Navigate to URL with `step=N` | `interview.goto(N)` |
| Click element matching next/forward button | `interview.nextButton.click()` |
| Fill input within `[data-field-name="UUID"]` | `stage.form.fillText(UUID, value)` or `fillNumber`/`fillDate` based on codebook component |
| Click radio within `[data-field-name="UUID"]` | `stage.form.selectRadio(UUID, optionLabel)` |
| Click checkbox within `[data-field-name="UUID"]` | `stage.form.selectCheckbox(UUID, optionLabel)` |
| Click toggle button within `[data-field-name="UUID"]` | `stage.form.selectToggleButton(UUID, optionLabel)` |
| Fill quick-add input + press Enter | `stage.quickAdd.addNode(value)` |
| Click "Add a person" button | `stage.nameGenerator.openAddForm()` |
| Click "Finished" button in dialog | `stage.nameGenerator.submitForm()` |
| Drag node from panel | `stage.nodePanel.dragNodeToMainList(label)` |
| Click node on sociogram (connecting) | `stage.sociogram.connectNodes(from, to)` |
| Drag node to ordinal bin | `stage.ordinalBin.dragNodeToBin(node, bin)` |
| Drag node to categorical bin | `stage.categoricalBin.dragNodeToBin(node, bin)` |

#### Determine Form Method from Codebook

Use the codebook variable's `component` (or `type` if no component) to pick the right form fixture method:

| Component | Method |
|---|---|
| `Text`, `TextArea` | `fillText` |
| `Number` | `fillNumber` |
| `DatePicker` | `fillDate` |
| `RadioGroup` | `selectRadio` |
| `LikertScale` | `selectLikert` |
| `CheckboxGroup` | `selectCheckbox` |
| `ToggleButtonGroup` | `selectToggleButton` |
| `Boolean` | `selectRadio` (options are "Yes"/"No" or custom labels from codebook) |

#### Comments

Add a comment above each form field interaction with the field's display name and component type:

```typescript
// 1. Date of birth (DatePicker)
await stage.form.fillDate('596c2ac2-...', '2000-06-15');

// 2. Gender identity (RadioGroup)
await stage.form.selectRadio('a06f06f5-...', 'Cisgender Male');
```

### Validation Tests

For each form stage (EgoForm, AlterForm, AlterEdgeForm), examine the codebook variables for targeted validation rules. Generate validation test assertions **within the happy path test** for that stage:

1. **Before filling fields**: Try to advance, verify validation blocks:
```typescript
// Verify validation blocks advancement
await interview.nextButton.click();
await expectURL(page, /step=N/); // Still on same stage

// Verify required field errors
await expect(
stage.form.getFieldError('field-uuid'),
).toBeVisible();
```

2. **Then fill fields normally** from the recording data.

Only test these validations (skip others):
- `required: true` — always test
- `minValue` / `maxValue` — test if present
- `minLength` / `maxLength` — test if present
- `pattern` — test if present
- `unique` — test if applicable (needs duplicate value scenario)
- `sameAs` / `differentFrom` — test if present

### Network State Verification

The sync middleware uses a 3-second debounce with leading+trailing edges. Each `interview.goto()` destroys the current page, killing any pending trailing-edge syncs. Stages that set data used by downstream skip logic or filtering must explicitly wait for that data to persist.

#### Form stages (EgoForm, AlterForm) must click Next to submit

Form data lives in React Hook Form's local state until the form is submitted. **You must click `interview.nextButton` at the end of every form stage** to flush the data to Redux. Without this, the sync middleware never sees the data.

For **EgoForm** stages, click Next as the last interaction (replaces the `toBeEnabled` assertion):

```typescript
// Submit form to flush data to Redux
await interview.nextButton.click();
```

For **AlterForm** stages with slides, click Next after filling the **last slide** (the earlier slides already submit when you click Next to advance):

```typescript
// Submit last slide to flush form data to Redux
await interview.nextButton.click();
```

Note: clicking Next navigates to the next stage, so the `afterEach` screenshot will capture the next stage's initial state rather than the current stage's final state.

#### Persistence waits for skip logic

After stages that set attributes consumed by downstream skip logic or filtering, add explicit waits using the protocol fixture. Available methods:

- `protocol.waitForNodes(interviewId, expectedCount)` — after node creation stages
- `protocol.waitForNode(interviewId, nodeName)` — when count alone is ambiguous
- `protocol.waitForNodeAttribute(interviewId, nodeName, attributeId)` — after CategoricalBin, OrdinalBin, or AlterForm stages (checks for non-null value)
- `protocol.waitForEgoAttribute(interviewId, attributeId, expectedValue)` — after EgoForm stages

Example for a CategoricalBin stage with downstream skip logic:

```typescript
test('Stage N: CategoricalBin', async ({ interview, stage, protocol }) => {
await interview.goto(N);

await stage.categoricalBin.dragNodeToBin('Dan', 'Yes');
await stage.categoricalBin.dragNodeToBin('Alice', 'No');

await expect(interview.nextButton).toBeEnabled();

// Wait for the LAST categorized node's attribute to persist
await protocol.waitForNodeAttribute(
interview.interviewId,
'Alice',
'variable-uuid',
);
});
```

**Always add `protocol` to the test's destructured fixtures** when using persistence waits.

### Stages With Placeholder Fixtures

Check the Fixture Availability Summary in STAGE_TEST_REFERENCE.md. If a stage type's fixture is marked **Placeholder**, generate a minimal test with a TODO referencing the placeholder:

```typescript
test('Stage N: Stage Label', async ({ page, interview }) => {
await interview.goto(N);

// TODO: stage.dyadCensus is a placeholder fixture — implement its
// interaction methods before writing full test assertions.
// See DyadCensusFixture JSDoc in stage-fixture.ts for the methods needed.
//
// Expected behavior from recording:
// - Dismiss intro panel
// - Select Yes/No for each node pair
// - Auto-advances after 350ms
});
```

Always reference the `stage.<fixtureName>` property (e.g., `stage.dyadCensus`, `stage.narrative`) so the test structure is ready — it just needs the fixture methods implemented. Never use raw Playwright selectors as a fallback.

### Skipped Stages

If the recording skips certain stage indices (e.g., conditional stages), add a comment:

```typescript
// Stages N-M are skipped (conditional on <condition from codebook>)
```

### Browser-Specific Skips

Add `test.skip()` for known browser limitations:

```typescript
// Skip geospatial on Firefox (no WebGL in Playwright's Firefox)
test.skip(browserName === 'firefox', 'Firefox lacks WebGL support in Playwright');
```

## Step 5: Verify Protocol File Location

Check if the `.netcanvas` file is already in `tests/e2e/data/`. If not, suggest copying it there and update the path constant accordingly.

## Step 6: Output Summary

After generating the test file, output:
1. Path to the generated test file
2. Number of stages covered
3. Number of validation tests included
4. List of stages with TODO placeholders (missing fixtures)
5. Suggested next steps (copy protocol to test data, run tests, etc.)

## Important Rules

- **Always use path aliases** (`~/tests/e2e/...`) for imports, never relative paths
- **Use `.js` extensions** in import paths (TypeScript with ESM)
- **Field names are UUIDs** — always use the variable UUID from the codebook, not the display name
- **Serial mode** — interview tests MUST use `test.describe.configure({ mode: 'serial' })`
- **Soft assertions for screenshots** — the `afterEach` capture pattern handles this via `interview.capture()`
- **No `console.log`** — project ESLint rule forbids it
- **Follow existing patterns** — match the style, structure, and conventions of `silos-protocol.spec.ts` exactly
23 changes: 23 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
.gitignore
.env*
.vscode
.idea
*.log
coverage
.nyc_output
.DS_Store
Thumbs.db
*.tsbuildinfo
tests/
docs/
*.md
storybook-static/
!package.json
!pnpm-lock.yaml
7 changes: 0 additions & 7 deletions .env

This file was deleted.

14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# -------------------
# Required environment variables
# -------------------
DATABASE_URL="postgres://user:password@host:5432/database?schema=public" # A pooled connection URL for Prisma.
DATABASE_URL_UNPOOLED="postgres://user:password@host:5432/database?schema=public" # A non-pooling connection URL for Prisma

# -------------------
# Optional environment variables - uncomment to use
# -------------------

#DISABLE_ANALYTICS # true or false - If true, the app will not send anonymous analytics and error data. Defaults to false.
#SANDBOX_MODE=false # true or false - if true, the app will use the sandbox mode, which disables resetting the database and other features
#PUBLIC_URL="http://yourdomain.com" # When using advanced deployment, this is required. Set to the domain name of your app
#USE_NEON_POSTGRES_ADAPTER=false # true or false - If true, uses Neon serverless PostgreSQL adapter instead of standard pg adapter. Required for Vercel/Netlify deployments with Neon. Defaults to false.
1 change: 0 additions & 1 deletion .eslintrc.js

This file was deleted.

Loading
Loading