Spaces:
Running
Running
Commit History
-
fix(ui): rework the sample-corpus section of Step 1
It looked bolted on, and it was: a grey slab inside the white card, the only element in Step 1 that was not a labelled field like the controls above it, reached through a collapsed link. Now it is the second branch of the step. An "or" rule separates it from the upload row, and it reuses the same .field label and control shape as Upload file / Corpus / Text column, so it belongs to the form instead of sitting in a box inside it. The select, the info button and Use share one height and one radius rather than being three different shapes. The collapse toggle is gone. It existed to keep the step quiet, but that is what hid the corpus name in the first place, and the picker is one row tall now, so there is nothing to hide. Scope is deliberately just this section; the rest of the workspace is untouched. Verified in a real browser at 1280 and 390 wide. That caught a mistake worth noting: an earlier edit had swallowed the closing brace of the 700px media query, so the new rules only appli…db5d011 -
fix(ui): show the sample corpus by default; stack the runs table on phones
Both reported 2026-09-08. The PI could not find CAMEL on the dev site, and a lab member hit the same thing plus a mobile layout problem. The sample-data panel started collapsed, so the only words on screen were "Use sample data" - the corpus is not named until you expand it, which is no help to someone looking for CAMEL. It now starts open. That is cheap because the panel is one row tall since the dropdown rework; the earlier objection was to two large cards, which no longer applies. On a phone the runs table pushed Status and View results past the right edge, so reaching the two things you open that table for meant scrolling sideways. Each run is now a stacked card with every field labelled from data-label. Nothing is dropped, and there is no horizontal scroll. Three things this walked into, all found by measuring in a real browser rather than reading the CSS: - the base rules are `table.docs td`, which outranks a bare `.docs td` and silently kept the table padding; - `@media (m…e639e13
-
docs(corpus): record the CAMEL licence; the dataset link is fine
Correcting an earlier claim of mine: the dataset link is NOT broken. The HF repo is public and GATED, not private - the page returns 200 for anyone, and only file downloads require signing in and accepting the terms, which is ordinary for a research dataset. I had tested the file URL and generalised it to the page. Checking that surfaced something that does matter. CAMEL is licensed CC BY-NC 4.0, and nothing in the repo said so, while README states the project is MIT and sample_data/camel_sample.csv - 999 rows of that corpus - sits in the tree. Nothing here relicenses it, but a reader had no way to know the sample carries different terms from the code around it. Examples now record their own licence. It shows in the info dialog and rides in run metadata next to the citation, so a researcher who exports results has the terms in the same file as the scores. README and sample_data/README name CC BY-NC 4.0 for the bundled sample explicitly and separate it from MIT, and the guide states i…5411f5f -
fix(ui): sample data picker is a dropdown with an info button
Choosing which corpus to run is a choice between mutually exclusive options, so it is a dropdown rather than a stack of rows: adding a dataset later costs one more option instead of another block of Step 1, and the panel stays one line tall whatever the catalogue holds. The per-entry About link becomes a single circular info button sized to the other controls, so it reads as part of the row rather than a glyph dropped into it. The dialog it opens now carries the CAMEL mark beside the name; the logo belongs there, on the dataset being described, and not in the picker, which lists several corpora and would imply they share a source. The selected entry keeps its one-line summary under the row, and an entry this instance cannot run is disabled in the dropdown, labelled "unavailable here", with the reason underneath. Drops the now-unused .samples-list, .sample-row, .sample-text, .sample-name, .sample-meta and .sample-actions rules rather than leaving them behind. Co-Authored-By: Claude …69aff04 -
fix(ui): sample data as a small entry point under the upload row
The PI's framing for CAMEL is a small "use sample data" call to action: from it a visitor sees the two available sizes, and can read about the data if they want to. The dropdown row did the opposite - it sat above the upload control and read as the first thing to do. Step 1 is now upload first. Under the row, one muted line ("No data of your own? Use sample data") expands in place into a two-row list: name, size, language, a one-line fit note, About, Use. About opens the provenance dialog (description, text column, preprocessing, citation, dataset link), which carries its own Use button so a reader can decide from there; Escape and the backdrop close it. The panel closes once a corpus is loaded, and the Corpus select echoes the sample's name rather than its filename. Sizes an instance cannot run stay listed with the reason and a disabled Use. Picking a size already in the project selects that copy instead of copying the corpus again, so a second click cannot duplicate 38 MB in the bu…0b5c981 -
fix(ui): one compact corpus row instead of two large cards
Three problems with the first cut, all fair. CAMEL appeared twice, as two "corpora". It is one dataset in two sizes, so the sizes are now options in a single dropdown and it reads as one dataset. It was badged DEFAULT, which overstates it. The PI asked for CAMEL to be "available and ready-to-use"; that is a starting point, not a claim that this is THE corpus. The field is renamed default -> preselected, it decides ordering and what loads first, and nothing is badged. The two expanded cards took most of Step 1 and pushed the upload control below the fold, which is the wrong hierarchy: most researchers bring their own data. Step 1 is now one labelled row - dropdown, info button, action - and the provenance (description, text column, preprocessing, citation, dataset link) moved into a modal behind the info button, where it is one click away without occupying the step. Also: the listing now knows this instance's row ceiling. The full corpus is 57,174 rows against a deployed CCR_MAX_ROW…bb4c28d -
feat(corpus): offer the full CAMEL corpus from R2, raise the row ceiling
Follows spec 0010, which shipped only a 999-text sample because the full corpus could not be ingested. CCR_MAX_ROWS goes to 100,000, which was the code default all along; the three docs that variously claimed 20,000 and 50,000 are corrected to agree with it and with each other. That removes the ceiling that made the 57,174-row corpus un-ingestible. The full corpus is served from R2 under examples/, not the repo: 38 MB would ride in the Docker image and the Space repo on every deploy. It is deliberately NOT fetched from Hugging Face at runtime - that dataset returns 401, so fetching it would mean shipping lab credentials in a public app. scripts/upload_example_corpus.py puts it there and prints the row count the catalogue entry has to declare. Selection downloads the master once to parse, then makes the user's copy with a server-side copy_object, so 38 MB does not travel back out through the application for every visitor. Verified against the live bucket: 7.0s fetch, 0.7s parse of 57…88b1ea9 -
feat(corpus): CAMEL as a built-in example corpus [spec 0010]
PI request from 2026-08-19: make the lab's CAMEL corpus the example data on the site so visitors can try CCR without uploading anything. Corpus details from Aliah 2026-09-06. Step 1 now offers an example corpus above the upload control. One click loads it, selects the declared text column, and the run proceeds through the normal ingest path, so nothing downstream changes. The citation and a link to the full dataset sit on the card, and a run on an example writes a corpus_source block into its metadata carrying the citation, source URL and preprocessing note: results produced on someone else's corpus have to stay attributable in the same file as the scores. Ships a 999-text SAMPLE rather than the full corpus, because the full one cannot be the bundled default: 57,174 rows exceeds CCR_MAX_ROWS (50,000 on both deployments) so ingest would refuse it outright, 38 MB against a 156 KB sample_data would ride in the Docker image and the Space repo, and a demo has to finish in seconds on 2 vCP…3a1d713
-
feat(ui): show language names instead of ISO codes
PI request: "change the name of languages from acronyms to actual names (e.g., ar -> Arabic)". Display only. Codes stay exactly as they were everywhere they are recorded - run metadata, the results CSV, construct YAML, and the structured fields on warnings - because those are the reproducibility record and the output contract, so exports and reproduction scripts are byte-identical to before. app/languages.py is the single source of the mapping so the UI and the warning text cannot drift apart. Renamed at every point a code reached a human: the text-language selector, the language column in the runs table, the model list's language coverage, and the three language warnings. The registry's named sets were leaking a machine identifier too, so xlm_roberta_100 now reads "100+ languages (XLM-RoBERTa coverage)" while models.yaml keeps the checkable name. /api/languages now returns {code, name} rather than a bare code list; its one existing assertion is updated. A coverage test asserts ever…41ee593 -
feat(privacy): anonymous session scope, construct TTL, creation cap [spec 0009]
Follows spec 0008, which scoped custom constructs to signed-in owners and left the anonymous tier as one shared bucket. Digging into that surfaced that three separate defects were being read as one "constructs are public" bug. No anonymous identity: owner_user_id == "" meant anonymous, so every anonymous visitor shared a bucket and saw everyone else's projects and constructs. Anonymous visitors now carry a signed session-id cookie and own their rows as "anon:<id>", so one column carries both ownership kinds and the shared bucket is retired for projects and constructs at once. Signing in ADOPTS that session's rows into the account: without it, scoping anonymous work to a session would strand it at sign-in, and it also replaces the reason 049074a left anonymous projects open to everybody. No lifecycle: retention.py imported Corpus, Job, Project - Construct was not in it, and constructs hang off no project, so nothing ever cascaded to them. Corpora go when a run finishes and projects ex…b35131c -
fix(privacy): scope custom constructs to their creator, add delete [spec 0008]
A PhD student reported seeing custom constructs on the public site that they had not created, with no way to remove them. Construct had no owner column at all, so every custom construct anyone typed was returned to every visitor by GET /api/constructs - listed, with some irony, under a picker heading reading "My custom constructs". This is the projects listing leak (049074a) one table over: that fix taught _visible_owners the right rule, but constructs had no ownership concept to correct. Construct gains owner_user_id, mirroring Project, and the listing applies the same rule: seeds are public, a signed-in user sees only their own custom constructs, anonymous ones stay in the shared anonymous bucket. Both columns are additive with scalar defaults, so auto_migrate_sqlite adds them to the deployed databases and existing constructs become anonymous - which removes them from every signed-in user's picker on upgrade, without a manual cleanup. Deletion is a confirmation dialog in the picker…3594eb6
-
feat(scoring): anchor vectors (bipolar constructs) [spec 0006]
Score texts along the axis between a target construct and a contrasting "opposite" construct: AV = target_centroid - opposite_centroid, anchor score = cosine(text, AV) (default) or dot(text, AV). Because embeddings are L2-normalized, a pole's CCR score (mean of per-item cosines) equals text . centroid, so the dot score is exactly target_score - opposite_score and the export is self-checking. - engine: run_ccr_anchored() (per-pole sims/scores + anchor score + metadata), reuses the doc-embedding cache; degenerate poles flagged. - data model: Job.opposite_construct_id + similarity_metric (additive columns). - runner: anchored export columns under output_schema_version 1.2, bipolar summary, both construct snapshots + scoring block in metadata, ANCHOR_DEGENERATE_POLES warning. - API: POST /api/jobs opposite_construct_id + similarity_metric, validated (single target, distinct poles, cosine|dot); JobOut echoes anchored fields. - reproduction script: anchored variant embeds both item …f341328
-
fix(ui): keep the AI drafting tooltip text inside its box
The info bubble inherited the base `button { white-space: nowrap }` rule, so its longest line ("Not a validated scale...") overflowed the 300px box instead of wrapping. Reset white-space (plus overflow-wrap) on .infotip-pop. Also switched the trigger from a <button> to a focusable <span>: the bubble nests a list and a link, which are invalid inside a button and made the "More in the guide" link unreliable. aria-label carries the full text for screen readers; the visual bubble is aria-hidden with its link out of the tab order.e8f94ba -
feat(guide): public how-to guide + live AI model details
Split the guides so the public gets a plain how-to page and the lab keeps its click-through testing guide: - /guide now serves a new public how-to guide (public_guide.html): the upload -> construct -> run -> export flow, the four ways to add a construct (library, typed, uploaded, AI drafting), a models table, and a reproducibility section covering the results CSV, run metadata, and the offline reproduction script. - /testing serves the original testing guide, gated to lab and above (same gate as /product); the 403 explainer points to the public guide. Header shows a lab-only Testing link. - Landing page links the PI's name (Mohammad Atari) to mohammadatari.com. - AI construct path shows "Drafted by <model>" with a hover/focus info bubble (model, provider, prompt version, item rules, daily cap). Model identity is read live from the API: new item_generation.public_info() surfaced as a `generation` block on /api/auth/me, so the tooltip and guide never hardcode a model that…8586c1b
-
ui: redesign the new-construct form as a contained panel with source cards
Tester feedback: the form read as cluttered - two levels of the same choice (entry buttons + tabs), every path's fields visible at once, and a flex-wrap bug stretching the Close button full-width. - One '+ New construct' entry; inside, three self-describing radio-cards (Type or paste / Upload a file / Draft with AI) - Only the chosen path's fields render, in task order; Reference hidden on the AI path, Description shown only there (required, drafts from it) - AI path: items box + Save appear once there's a draft to review; quota sits inline next to the Draft button - Panel is a bordered sub-card with its own header + close069d95d -
feat: audit trail for AI drafts + disabled-button reasons everywhere
- ConstructGeneration.items stores the ORIGINAL drafted items (PI request 2026-08-07): run metadata now shows the as-drafted text alongside the researcher's saved/edited items - Draft-items button disabled until Name + Description exist, reason inline (same pattern as Save; errors in the top banner go unseen) - Run button gets a 'To run, still needed: ...' line when disabled - AI generation quota shown from tab-open via auth/me, not only after the first draftc49bb09 -
ui: three explicit construct paths + Save gating + visible AI drafts
PI test feedback (2026-08-07): - Step 2 hint enumerates the three acquisition paths; two buttons next to the picker ('+ Your own items', 'Draft with AI') replace the generic '+ Custom construct' - Save construct is disabled until name + items exist, with an inline line saying what's missing (the silent dead-click read as broken - the error banner sits at the top of the page, out of view) - After drafting, scroll/focus the items box and say 'N items drafted - they're in the box below' (drafts landed off-screen unnoticed) - /guide and MANUAL_TESTING.md updated to the new button namesdc9da41
-
ui: item-source chooser in custom-construct form (type / upload / AI)
The flat form stacked all three item sources at once and read as clutter (tester feedback); now a segmented chooser shows one source's controls at a time, with the items textarea below as the shared review surface. Also fixes the Draft-items button baseline (field-row aligns controls).6e3ac9f -
feat: LLM-generated construct items (design note ITEM_GENERATION.md)
Draft questionnaire items for a construct from its name + explanation, for use as CCR item sets when no validated scale exists (PI idea 2026-07-31; decisions 2026-08-05: positively-keyed only, signed-in only, PI-approved prompt v1 and cautionary wording). - POST /api/constructs/generate-items: preview-only into the existing review-and-save flow; 20/day per-user cap (generation_events table) - Providers: Groq free tier (llama-3.3-70b, interim) / Anthropic Haiku (target once billing lands); auto-selected from which key is set - Provenance: Construct.generation_json -> ai_generated in the API, source_type llm_generated + cautionary note in run-metadata snapshots - UI: draft-with-AI section in the custom-construct form (library name-match warning), AI-generated badges in picker/selection/results - Live smoke test: scripts/smoke_test_generation.py (Groq verified)1a28176
-
feat: Implement multi-construct functionality in CCR analysis
- Updated frontend components to support selection of multiple constructs in the ConstructPicker. - Modified Workspace to handle an array of construct IDs instead of a single ID. - Enhanced ResultsView to display results for multiple constructs, including a correlation matrix. - Added tests for multi-construct runs to ensure correct behavior and output. - Updated styles to accommodate new UI elements for multi-construct selection and display. - Adjusted metadata handling to reflect changes in construct selection and results.a685524
-
Upload limits: make the byte ceiling configurable and stream-checked
The 25 MB cap was hardcoded, unlike every other limit, and was the wrong axis: embedding cost scales with rows and tokens, not file bytes. On the deployed Space (CCR_MAX_ROWS=20000) it only bound for rows averaging over ~1.3 KB, i.e. long-document corpora - the exact shape the planned chunking feature makes more common. - MAX_UPLOAD_BYTES -> max_upload_bytes(), env-configurable via CCR_MAX_UPLOAD_BYTES, default 50 MB. It is now an OOM/abuse backstop; CCR_MAX_ROWS remains the limit that bounds job cost. - Stream uploads in 1 MB chunks and reject mid-transfer. Previously the whole payload was read into memory *before* the size check, so an oversized upload was fully resident before being refused. Partial temp files are cleaned up on any failure, including client disconnect. - Anonymous byte cap 2 MB -> 5 MB: 200 rows of long documents (200 x 8 KB transcripts ~ 1.6 MB) sat uncomfortably close to the old ceiling. The 200-row cap is unchanged and remains what actually binds f…776393c
-
Graceful handling when an uploaded file is gone (restart-safe UX)
3f7c413
-
Sync platform from lab mainline: dev instance ready to deploy
Full feature set: accounts (email/password + feature-flagged Google via Supabase PKCE), anonymous tiers (3 runs/day, delete-after-analysis, 24h purge), saved-run cap, construct upload from CSV/XLSX, structured warnings + language detection, model registry (MiniLM/E5), per-run reproduction scripts, corpus-embedding cache, storage interface (local/ R2), sample-data test kit, MANUAL_TESTING.md. Rights guard: only the 5 original seed constructs ship in this public repo; the imported lab collection stays out pending the redistribution decision. HF remote URL detokenized. 64 tests passing.4b09d2d
-
CCR Platform: web platform for Contextualized Construct Representations
Upload a corpus, select or define a validated psychological construct, run CCR analysis with locally-hosted sentence embeddings, inspect per-item loadings and score distributions, export results with a reproducibility record. - FastAPI backend, SQLite, worker-queue jobs with orphan recovery - React dashboard (prebuilt; no Node needed to run) - Tolerant corpus ingestion (encodings, delimiters, caps, warnings) - Seeded construct library with citations; custom constructs - 17 tests via a deterministic embedding backend (no ML deps needed) - Docker deploy for Hugging Face Spaces / Cloud Rund69ace5