Commit Graph

81 Commits

Author SHA1 Message Date
Experiments DB Dev 600323f40a feat(export): generalized buildMatrix over assignable dimensions 2026-07-19 13:22:53 -04:00
Experiments DB Dev 7d112de0d7 feat(export): subject/parameter members + dimension dispatcher 2026-07-19 13:19:15 -04:00
Experiments DB Dev a411d59305 feat(export): dimension primitives, date members, status index 2026-07-19 13:16:33 -04:00
Experiments DB Dev cd4e213d6f docs(plan): configurable data export implementation plan
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 13:14:41 -04:00
Experiments DB Dev 900759074d docs(spec): configurable data export — assignable axes + subject group cell
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 13:09:07 -04:00
Experiments DB Dev 57446d5b64 Merge branch 'feat/experiment-data-export'
Client-side CSV export on the experiment page: pick a daily parameter
(session metrics or any daily-record field) and download a date×subject matrix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 16:21:07 -04:00
Experiments DB Dev ea1a7f39f2 feat(frontend): Export data button + modal on experiment page 2026-07-06 15:48:02 -04:00
Experiments DB Dev 0bf3fc479b refactor(frontend): polish ExportDataModal (derived selection, safe URL revoke, error escape) 2026-07-06 15:46:52 -04:00
Experiments DB Dev ea76cf9cd2 feat(frontend): ExportDataModal — pick a parameter and download CSV 2026-07-06 15:42:30 -04:00
Experiments DB Dev dfe3938afc feat(frontend): toCSV + csvFilename for data export 2026-07-06 15:40:24 -04:00
Experiments DB Dev b5578f6e24 feat(frontend): buildMatrix pivots statuses into date×subject grid 2026-07-06 15:37:33 -04:00
Experiments DB Dev 3f8febfda3 feat(frontend): listExportableParams enumerates export options 2026-07-06 15:35:19 -04:00
Experiments DB Dev 523cf1614e feat(frontend): extractValue helper for data export 2026-07-06 15:33:30 -04:00
Experiments DB Dev 9b55b578f2 docs: implementation plan for experiment data export (CSV)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 15:30:41 -04:00
Experiments DB Dev 2d3b7c4607 docs: design for experiment data export (CSV)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 15:25:25 -04:00
Experiments DB Dev 740a884efa Merge: persist cross-subject plot config per experiment 2026-06-01 10:34:54 -04:00
Experiments DB Dev b0c6217cb4 fix(backend): widen plot_config size cap to fit a full hiddenSubjects list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 10:30:06 -04:00
Experiments DB Dev 9a9b5dfae8 feat(frontend): hydrate + debounced-persist cross-subject plot config
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 10:26:33 -04:00
Experiments DB Dev 4b82df514f feat(frontend): serialize/read helpers for plot config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 10:18:56 -04:00
Experiments DB Dev e9511bdac3 feat(backend): persist per-experiment plot_config via PUT /:id/plot-config
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 10:14:50 -04:00
Experiments DB Dev 2dd4a329ee docs: implementation plan for persisting plot config
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 10:10:39 -04:00
Experiments DB Dev 8877747a63 docs: design for persisting cross-subject plot config per experiment
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 10:06:40 -04:00
Experiments DB Dev c768b5829a Merge: cross-subject plot interactions (sidebar, legend toggle/highlight, ordered tooltip) 2026-06-01 09:56:41 -04:00
Experiments DB Dev 839d05f449 feat(frontend): subject sidebar, legend toggle/highlight, ordered tooltip on cross-subject plot
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 09:41:43 -04:00
Experiments DB Dev 7b34c2fa52 feat(frontend): add SubjectSidebar visibility panel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:33:17 -04:00
Experiments DB Dev 0f7f6fbbe3 feat(frontend): pure helpers for cross-subject plot interactions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 09:29:21 -04:00
Experiments DB Dev d77b6c1528 docs: implementation plan for cross-subject plot interactions
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 09:26:00 -04:00
Experiments DB Dev 3095628479 docs: design for cross-subject plot interactions
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 08:45:46 -04:00
Experiments DB Dev 1b0f083cc5 feat(frontend): persist bucket config to animal on successful analysis
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 08:05:07 -04:00
Experiments DB Dev 75a343d617 feat(frontend): render numerical-bucket plots in CSV-analysis results
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 08:03:48 -04:00
Experiments DB Dev 39c01c567c feat(frontend): add field picker + numerical bucket UI in classify phase
Replaces "+ New category" with a Note/Numerical type-aware picker, extends
CategoryBucket to render type badges, bulk-add, and custom-bucket remove controls,
and deletes the addCategory() back-compat shim from Task 7.
2026-05-01 08:01:41 -04:00
Experiments DB Dev ef17ee0642 feat(frontend): seed CsvAnalysis buckets from animal config 2026-05-01 07:58:56 -04:00
Experiments DB Dev ceaa3be200 refactor(frontend): unify CsvAnalysis state under buckets[] 2026-05-01 07:56:22 -04:00
Experiments DB Dev b9b8a4ef1d feat(frontend): add computeNumericSeries helper 2026-05-01 07:51:22 -04:00
Experiments DB Dev 0b83795665 feat(frontend): add extractNumber helper 2026-05-01 07:50:56 -04:00
Experiments DB Dev 6a6e6b310a feat(frontend): add animalsApi.updateCsvConfig
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 07:49:41 -04:00
Experiments DB Dev fe4e89f497 feat(backend): PATCH /animals/:id/csv-config endpoint
Implement TDD for new route that accepts CSV configuration with validated buckets.
Route uses auditMiddleware to log config changes and delegates validation to
validateCsvConfig helper from Task 2.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 07:49:00 -04:00
Experiments DB Dev 1ae55591f4 feat(backend): add csv_analysis_config validator 2026-05-01 07:47:17 -04:00
Experiments DB Dev 7b023fb8a3 feat(db): add csv_analysis_config JSON column to animals 2026-05-01 07:43:58 -04:00
Experiments DB Dev cdff6732b0 feat: manual metrics editor + past-analyses inline viewer on daily status
- AnalysisSummaryCard gains an "Edit manually" affordance powered by
  the new ManualMetricsForm (add/remove categories, edit counts,
  recompute total + success rate).
- New PastAnalysesViewer renders a tab-style selector of saved CSV
  analyses with an inline AnalysisResultsView panel.
- Reorganizes the page so the manual-metrics path is reachable when no
  analysis_summary exists yet.
- Sync package-lock to the recharts ^2.15.4 already declared in package.json.
2026-05-01 07:40:10 -04:00
Experiments DB Dev 69ce5fbeab docs: add implementation plan for numerical CSV-analysis buckets
12-task TDD plan covering DB backup, schema migration, backend
PATCH endpoint with validator, frontend lib helpers (extractNumber,
computeNumericSeries), CsvAnalysis state refactor, type-aware field
picker, numerical plot rendering, and per-animal config persistence.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 07:36:44 -04:00
Experiments DB Dev 2ed69aa6d6 docs: add design spec for numerical CSV-analysis buckets per animal
Spec for adding a numerical bucket type to CSV analysis that plots
note values (numeric portion) against frame/timestamp, persisted on
the Animal model so subsequent uploads reuse the configuration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 07:30:18 -04:00
Experiments DB Dev ee2cf19b74 test: add analysisOnly regression tests; fix cache isolation in tests
New file tests/experimentDailyStatuses.test.js — 9 tests covering
GET /api/experiments/:id/daily-statuses:
  - 404 on unknown experiment
  - all statuses returned when no filter
  - analysisOnly=true keeps only non-null analysis_summary records
  - analysisOnly=true returns [] when none have analysis_summary
  - the exact null/object mix that caused the production 500 now passes
  - analysisOnly=false (explicit) returns all records
  - ?date= param is forwarded to Prisma correctly
  - empty-array response on zero statuses
  - returned records include expected fields

Fixed tests/calendar.test.js: existing tests were silently broken by the
cache added in the perf commit. Both test files now mock lib/cache to
always miss, so each test exercises the real route logic in isolation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 15:11:21 -04:00
Experiments DB Dev d125d2e365 fix: filter analysis_summary in JS instead of Prisma WHERE clause
Prisma 5 rejects both null and Prisma.DbNull as WHERE filter values for
Json? fields (no clean IS NOT NULL operator). Filter the result array in
JS after the query — the output is immediately cached so this only runs
once per cache period.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 14:54:08 -04:00
Experiments DB Dev c0d0b8e6ba fix: use Prisma.DbNull to filter non-null Json? field in analysisOnly
Prisma 5 rejects JS null as a where-clause value on Json? fields.
Use Prisma.DbNull (SQL NULL sentinel) so the NOT filter compiles correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 14:47:50 -04:00
Experiments DB Dev 5c0703c271 feat: per-chart customization — size, Y range, X zoom, independent X/Y data
Each chart card now has a "▾ customize" button. Clicking it reveals a
settings bar (only rendered when active — zero cost when collapsed):

  Size      — S / M / L height selector
  Y range   — min / max inputs to set the YAxis domain
  X zoom    — min / max inputs to clip the displayed X domain
  X data    — per-chart X field override, independent from the shared
              global X selector (each chart can use a different field)
  Y lines   — (counts chart only) toggle individual category lines on/off
  ↺ Reset   — shown only when any setting has been changed from default

The global X-axis selector and tick-step control remain at the component
level as the persistent defaults. Per-chart overrides are session-only
(non-persistent), resetting on page load.

Performance: animalRows computation in ExperimentAnalysisCharts is now
split from the per-chart data step, so a metric/X change only recomputes
the affected chart. Per-chart data only recomputes when that chart's
xFieldOverride changes; shared data is reused otherwise.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 14:36:19 -04:00
Experiments DB Dev d2c8d69718 perf: server-side caching + remove bulk status fetch from experiment page
- Add backend/src/lib/cache.js — in-process TTL Map cache with
  prefix-based invalidation; no external dependencies

- Cache /experiments/:id/calendar?field=X per (experimentId, field).
  Invalidated immediately on any DailyStatus write.

- Cache /experiments/:id/daily-statuses per (experimentId, date, analysisOnly).
  Invalidated immediately on any DailyStatus write (create/update/delete
  and analysis-summary saves all clear the relevant prefix).

- Add ?analysisOnly=true to /daily-statuses: filters rows where
  analysis_summary IS NOT NULL. Charts are the only consumer and already
  discard rows without analysis data; pre-filtering server-side avoids
  sending the full status payload (71 rows → 1 for this experiment).

- ExperimentCalendar: remove allStatuses prop, fetch calendar data
  directly via API. The component now issues one small GET per field
  selection change instead of the parent loading thousands of rows upfront.

- ExperimentDetail: pass analysisOnly:true to getDailyStatuses;
  drop allStatuses prop from ExperimentCalendar. Cold experiment page
  load no longer fetches every daily status record.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 14:03:59 -04:00
Experiments DB Dev 52d5fca5d1 feat: store matching metadata on session file registration
Each saved file now records three additional fields:
  matched_identifier    — the literal animal_id_string or animal_name
                          substring that matched in the filename
  animal_id_string_snap — snapshot of animal.animal_id_string at
                          registration time
  animal_name_snap      — snapshot of animal.animal_name at
                          registration time

This lets future consumers (scripts, exports, re-matching) identify
the subject from the file record alone, even if animal data changes.
The matched identifier is also shown in the drop preview UI (↳ 2852).

Tests: 25 total (+2 for new payload fields).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 13:41:36 -04:00
Experiments DB Dev 5cd6d2a8a3 fix: move session file registry above modification history
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 13:37:30 -04:00
Experiments DB Dev b73768ee29 feat: add session file registry to daily status detail page
FileDropZone now appears on each subject's individual daily status
page, scoped to that one status. Files are matched against that
subject's animal_id_string and animal_name.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 13:36:33 -04:00