Spaces:
Running
Running
Commit History
-
feat(ui): drop the dark banner; the sidebar is the chrome now
"Every modern website doesn't have an explicit header these days, ours looks old school" (2026-09-15). The banner sat on every screen, carried the product's full name, and cost vertical space on a phone to say something the landing page already says. The dashboard now has no top chrome at all, the way ChatGPT and Claude have none: the sidebar holds the logo, the guides, the admin link and the account, and the content area starts at the content. The landing page and /admin have no sidebar, so they keep a bar, but a light and quiet one with no tagline. The three static doc pages get the same treatment, and their inline logo strokes with currentColor, which is what lets one mark serve both their light and dark themes. Two things this forced, both right anyway. The dashboard became a real app shell (100vh, each pane scrolling inside it): stretched by a long page, the sidebar's account row and New project button had drifted to the bottom of the document instead of sitting at the bottom of…3967e32
-
feat(cite): one canonical citation for the platform and the CCR papers
Ali Hajian asked for a Google Scholar style Cite button (2026-09-09). The strings behind it live in app/citation.py and nowhere else: the dialog, the BibTeX and RIS exports, and the repo's new CITATION.cff all read from there, and a test fails if the .cff drifts. A citation that says two different things in two places is worse than no button. GET /api/citation is public, since the dialog sits on the landing page that signed-out visitors see. It returns the platform reference in APA, MLA, Chicago, Harvard and Vancouver, the two CCR papers a methods section needs beside it, and BibTeX and RIS containing all three. PLATFORM_VERSION moves to app/version.py so citation.py and jobs.py read the same constant: the version a paper cites is then the version stamped into the run metadata and the reproduction script that produced its numbers. Both papers were taken from Crossref, not from memory: 10.31234/osf.io/m93pd (Atari, Omrani & Dehghani 2023) and 10.18653/v1/2024.emnlp-main.151 (Chen, Li…b64a521
-
fix(guide): wrap the reproduction commands on a phone
The page had no `pre` styling at all, so the two-line pip/python block set the layout width: 485px inside a 390px screen. Every paragraph on the guide then scrolled sideways, and the fixed "Top" link sat off the right edge. The block scrolls at its own edge now and the commands wrap rather than overflow.e2d93c2
-
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(storage): do not require server-side copy for example corpora
Loading the full CAMEL corpus 500'd on the lab's deployment. The cause is not ours: R2 CopyObject is unavailable on that bucket, answering NoSuchKey for an object head_object resolves in the same session and with both CopySource forms. The dev account copies the identical 38 MB file without complaint, so this varies by account and cannot be relied on. The server-side copy was only ever an optimisation - it avoids reading 38 MB back out through the app per visitor. The caller has already downloaded the file to parse it, so the fallback is to upload that local copy: one upload, no extra fetch, and it works on any S3-compatible backend. Verified against the lab's bucket, where it now succeeds and leaves the master object intact. Note for whoever adds the next deployment: dev and prod are separate Cloudflare accounts, so the master file needs uploading once per account with scripts/upload_example_corpus.py. The catalogue only stores the key. Co-Authored-By: Claude Opus 5 (1M context) <n…82c5ea2 -
feat(library): settle the last two wording questions; CAMEL logo
Both decisions confirmed with the PI on 2026-09-07, so no construct in the library is left without a verification decision. IPIP keeps its leading "I". Worth recording why the question dissolved: the platform never added it. import_from_xlsx.py only strips whitespace, and the items arrived with the "I" already present in the commit that first created the library, from lib.xlsx. The IPIP source really does print bare stems ("Feel little concern for others") with the subject supplied by its instruction header, so the reviewer's observation was right about the state and wrong about the cause: this is a transcription convention in the lab's own spreadsheet. The five constructs are verified with that provenance recorded on each. K10 is retired rather than rewritten. Its items are fragments under a shared header, and CCR embeds item text directly, so "worthless?" is a poor stand-in for the construct. Archived, not deleted: constructs are append-only and any run that used it must still reso…726d852 -
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 -
fix(anon): owner key overflowed owner_user_id, 500ing anonymous writes
Live outage on both deployments since spec 0009 shipped on 2026-09-04: POST /api/projects and POST /api/constructs returned 500 for anyone not signed in, which is the entire anonymous try-it path. ANON_PREFIX + secrets.token_hex(16) is 37 characters and both owner_user_id columns are String(32). SQLite ignores VARCHAR limits so all 162 tests passed locally; PostgreSQL enforces them, so every anonymous insert was rejected. Signed-in users were unaffected because a user id is exactly 32 characters, which is why nobody reported it - lab members are signed in. Shortened the session id to 13 bytes (104 bits of entropy, key length 31) rather than widening the column. A type change is not additive, so auto_migrate_sqlite would not apply it and both deployed databases would have needed hand-run DDL; this deploys as-is. No data is lost because no anon: row was ever successfully written. The regression test reads the column width from the model rather than hardcoding it, and asserts against t…a7f2409 -
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
-
fix(retention): delete project rows in FK-safe order, enforce FKs in SQLite
delete_project_cascade removed jobs, then corpora, then the project, which is the right order to write but not the order that reached the database. Within a single flush SQLAlchemy sorts DELETEs by mapper dependency, and Job has no ORM relationship to Corpus (only a raw ForeignKey column), so it was free to emit DELETE FROM corpora first and violate jobs_corpus_id_fkey. Postgres enforces that constraint, SQLite does not unless foreign_keys is ON, so this only ever failed on a deployed instance: - DELETE /api/projects/{id} returned 500 (also the /admin delete path). - purge_expired_anonymous shares the cascade, so the hourly retention sweep raised on the first expired project that had ever been run and purged nothing after it. Anonymous projects and runs outlived CCR_ANON_TTL_HOURS; the dev database still holds one from 2026-08-06. Uploaded files were never affected, since an anonymous run's corpus is deleted when the run finishes. Fix is a flush between levels, so each level…248d767 -
fix(constructs): correct the review pass after a validity review
A research-validity review of the previous commit found four real problems. All four are fixed here. Two of the reviewer's wording corrections moved an item AWAY from the publication its construct cites, and I had applied them under a `verified` badge. Checked against the sources: the published MFQ30 reads "treated differently than others" (not "from"), and Edmondson (1999) reads "It is safe to take a risk on this team" (not "in") - the proposed "in this team" comes from a third-party questionnaire, whose URL I had also promoted over the working Edmondson PDF. Both items keep their published wording, both constructs are held back as unverified with the disagreement recorded, and the source_url override is dropped. The reviewer's item-ORDER findings for rses and cbi_work_related_burnout were silently dropped: my classifier only read notes on rows that failed one of the four checks, and these sat on rows marked OK. Order feeds item_hash and decides what sim_item_N means, so both are no…461b859 -
feat(constructs): apply the 2026-08-25 library review [spec 0007]
Noor Skhiri reviewed all 525 items across the 94 constructs (wording, reverse keying, subscale grouping, citations). This applies it. Split by what item_hash covers. Item changes ship as a NEW version: 61 reverse-scoring flags corrected across 14 constructs (35 -> 96 flagged items), 9 verbatim wording fixes, and one SCS-SF item moved to Over-identification per the source coding key. 23 constructs gain a version 2; their version 1 files keep their original items and are marked archived so runs that pinned them still resolve. Everything outside the hash is edited in place: 88 constructs promoted to verified with reviewer and date recorded, plus citation and source_url repairs. Six constructs stay needs_verification pending two PI decisions (the IPIP "I" prefix and the K10 stem). Two loader gaps had to close for this to ship: sync_library was insert-only, so a status change could never reach an already-seeded database, and the picker listed every version, so a v2 would show the same co…4afd259
-
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
-
feat(guide): add a sample-datasets section to the public guide
Links the four ready-to-run example corpora (served at /samples) so new users can try CCR without uploading their own data, with a pointer from the upload step. Suggested by Meriel Burnett. CHANGELOG also records the footer and project-privacy fixes.c993be8 -
fix(privacy): stop showing shared anonymous projects to signed-in users
_visible_owners() returned ("", user_id) for a signed-in user, so every signed-in account saw the shared anonymous bucket (owner_user_id == ""): projects anyone created without signing in. Signed-in users now see only their own projects. Anonymous projects stay open by direct access so the anonymous -> sign-in continuity flow keeps working; they just no longer appear in a signed-in user's project list. Adds a regression test.049074a
-
fix(auth): trim whitespace from CCR_APP_URL to prevent sign-in issues
docs: update deployment instructions and clarify CCR_APP_URL usage test: add test for app_url to handle pasted whitespace in CCR_APP_URL chore: update reverse proxy worker with correct upstream host3fde616
-
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
-
docs: AI item-drafting scenarios in /guide and MANUAL_TESTING.md
Click-through test steps for the Draft-with-AI tab (happy path, review labeling, library guardrail, vague input, provenance in metadata, daily cap, signed-out/no-key behavior) + the 20/day row in the limits table.bf6c4d6 -
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
-
content: link the lab website (websites.umass.edu/matari)
'Who runs this' on the landing page links the lab name; /product's Questions section gets the same link.2a166b5 -
style: enhance topbar consistency and responsiveness across guide and product pages
c53fa39 -
feat: put invite links on hold; single brand header everywhere
Invite links are dormant behind CCR_INVITES_ENABLED (default off): creation 409s, existing tokens stop redeeming with a clear message, /admin hides the section. Pre-assigned roles remain the onboarding path; machinery and audit history stay intact for re-enabling. Header: the CCR logo (which already reads 'CCR') stands alone with the tagline 'Psychological Text Analysis with Contextualized Construct Representation' - app, guide, and product topbars now identical.6a6c7cf -
feat: make /product internal - lab members, maintainers, and PI only
Anonymous and external visitors get a friendly 403 explainer instead of the architecture/access-model docs (PI request 2026-07-31). The app header and public welcome page stop advertising the link to everyone else; the server enforces the gate via the new auth.role_lab_or_above helper.78fa678 -
feat: CAML lab branding - CCR logo, ink+teal theme, favicon, attribution
Palette derived from the lab's CCR logo: ink (#151515) header bars with the white logo variant, darkened logo teal (#26736f) for links/buttons (AA on white), pure logo teal (#339B98) for data fills. Correlation matrix now diverges teal (positive) vs copper (negative). Applied across the React app, guide, and product pages with 'Culture & Morality Lab, UMass Amherst' attribution.4e87534
-
feat: Add multi-construct functionality to scoring and results in guide and product pages
b195b7b -
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
-
refactor: enhance AdminPage overview display and improve navigation
- Added a Stat component to better visualize user statistics on the AdminPage. - Updated the overview section to use the new Stat component for a cleaner layout. - Improved the header navigation in App component for better user experience. - Changed the brand header to a link for easier navigation back to the dashboard. - Enhanced styling for header elements and added hover effects for links. - Updated empty state messaging and layout in the App component for clarity. - Refined CSS styles for better visual consistency and responsiveness.54bd1cf -
feat: add welcome page for first-time users and update routing
- Introduced a new WelcomePage component to guide first-time visitors through the platform's features and usage. - Updated App component to conditionally render the WelcomePage based on user navigation and localStorage state. - Modified test cases to include the new /welcome route. - Updated styles to accommodate the new welcome page layout and design. - Changed asset references in index.html for updated frontend build.8ed8f32 -
Enable Row-Level Security on public tables in Supabase at startup
8cc4299 -
Refactor admin page to include collapsible sections and enhance invite link management
- Added a collapsible Section component to improve layout and readability of the AdminPage. - Integrated invite link management, allowing admins to view, copy, and revoke invite links. - Updated tests to verify invite link functionality, including status checks and revocation behavior. - Enhanced UI elements for better user experience, including status indicators for invites and improved error handling.5ad96fc -
Four-tier access model: self-governing admin, pre-login access, audit trail
PI decisions 2026-07-22: - Roles: pi | maintainer | lab | external (legacy "member" reads as external). Lab members and above: unlimited saved runs. - PI role holds escalation rights in-app (grant/revoke staff, act on staff accounts, audit view); ADMIN_EMAILS is bootstrap + break-glass only. Maintainers get the operational surface. Nobody can change their own role. - Construct verification is maintainer-only (the RA's job); PI/admin keep a read-only queue. - Access before sign-in: email-bound pre-assigned roles (staff-capable, claimed on first password/Google sign-in) and signed 7-day invite links (lab/external only, ?invite= signup flow). - Append-only admin_audit table records every admin action; visible to PI/env admins. - Docs split: /guide = navigate-and-test; new /product page = access model + capability matrix + architecture (moved from guide).bfb6467 -
Repro script: valid Python booleans + per-run filenames in instructions
- ITEMS was rendered with json.dumps, emitting true/false: valid Python syntax (bare identifiers) but a NameError at runtime. Now a real Python literal (True/False); test literal_evals the block so JSON booleans can't slip through compile() again. - Script/requirements usage instructions now name the files exactly as they download (run-id suffix) and use the uploaded CSV as the example arg; download endpoints share the same filename helpers so names can't drift. Guide + MANUAL_TESTING updated to match.ffe862f
-
Fix deprecated model_args->model_kwargs in ST loader + repro script
sentence-transformers renamed Transformer(model_args=) to model_kwargs. The pooling-fallback loader only passes it when a revision is set, so the deprecation warning began firing once the models were pinned. Apply the same rename in the generated reproduction script so exported scripts stay warning-clean on current sentence-transformers. Behavior-preserving: verified identical scores across all four PsyEmbedding models.c5ee930
-
Guide: click a section heading to copy a shareable deep-link
Sections already had stable ids (so /guide#limits worked), but there was no way to discover or grab that link. Each id'd heading now shows a "#" on hover and is click-to-copy: clicking sets the URL hash (scrolling to and briefly flashing the section) and copies the full link to the clipboard, with a small toast. Progressive enhancement - if the script fails, headings still render and the ids still deep-link natively. Respects prefers-reduced-motion.46b1454 -
Guide: add limits + models tables, fix stale anon byte cap
Testers were asking what the limits and available models are (Ali, Slack) - the answers were scattered across sections 2/7/8 and the anon byte cap still read 2 MB after we raised it to 5 MB. Add two at-a-glance tables right after the quickstart: - Limits by tier (upload size, rows, runs/day, saved runs) so the signed-out vs signed-in vs lab differences are in one place. - Models available, flagging the four PsyEmbedding fine-tunes and the first-run download so nobody reads the lazy-load pause as a hang. Also corrects the stale "2 MB" anon hint to 5 MB.329d800
-
new upload restrictions
a9d817a -
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
-
Guide: add architecture + data-flow diagrams and infra/data-lifecycle notes
New 'How it works' section for technical readers: two inline SVG diagrams (what-runs-where, and the CCR run data flow), where-your-data-lives, and key engineering choices. Top caveat updated - files persist now too (R2).d7891e4 -
Graceful handling when an uploaded file is gone (restart-safe UX)
3f7c413 -
Guide: accounts/data now persist (Postgres); files caveat clarified
0b29b70 -
Persistent storage: DATABASE_URL (Postgres/Supabase) support + deploy steps
f825419 -
Admin: no password reset for Google accounts (UI + backend guard)
5a24540