Skip to content

Release v0.6.2#162

Merged
neuromechanist merged 11 commits into
mainfrom
develop
Feb 7, 2026
Merged

Release v0.6.2#162
neuromechanist merged 11 commits into
mainfrom
develop

Conversation

@neuromechanist

Copy link
Copy Markdown
Member

Summary

Release v0.6.2 from develop to main.

Changes since v0.6.1

Test plan

  • All 1352 tests pass on develop
  • CI green on develop
  • CI passes on this PR
  • Verify prod deployment after merge

neuromechanist and others added 7 commits February 6, 2026 18:57
* feat: add NEMAR community assistant for dataset discovery

Add new NEMAR assistant that helps researchers find and explore
BIDS-formatted EEG/MEG/iEEG datasets from nemar.org via its
public API. Includes search/filter tool and detail retrieval tool
with client-side filtering (API has no server-side search).
Also adds .context/nemar-api.md for future API reference.

* test: add tests for NEMAR tools against live API

Tests cover: helper functions (_parse_sep_field, _matches),
API fetch, search with various filters, dataset detail retrieval,
edge cases (nonexistent datasets, no results). 93% coverage on
tools.py. All tests use real NEMAR API, no mocks.

* fix: address PR review findings for NEMAR tools

- Add 5-minute TTL cache for _fetch_all_datasets() to avoid
  hitting API on every search call
- Move response parsing inside try/except in get_nemar_dataset_details
- Add dataset_id input validation (ds + 4-6 digits)
- Handle JSONDecodeError, non-numeric keys defensively
- Log warning on empty API response instead of silent return
- Narrow generic Exception catches; don't leak internals to users
- Fix system prompt: "descriptions" -> actual searched fields
- Fix docstring: "sorted by dataset ID" -> "in API response order"
- Add tests for validation, caching (45 tests, all pass)

* fix: address minor comment review findings

- Fix "one-line" docstring on multi-line _format_summary
- Clarify has_hed parameter behavior (None has no effect)
- Remove -k (insecure) from curl examples in API docs

* feat: add NEMAR to demo page, mark BIDS as active

- Add NEMAR community card with widget config and suggested questions
- Change BIDS status from 'soon' to 'active' (backend already available)
- Update README to list all 4 active communities

* fix: make knowledge tools test config-aware

The test assumed all communities have github and citations sections,
which generates discussions/recent/papers tools. NEMAR is a data
portal with custom tools instead. Test now checks config to determine
which auto-generated tools to expect.
Prevents non-fast-forward push failures when develop advances
between checkout and push (race with other workflows).
* fix: boost exact symbol_name matches in docstring search

When searching docstrings, exact symbol_name and file basename
matches now rank above BM25 results. This fixes the erpimage
function being buried at rank 10 due to BM25 term frequency
dilution from its large docstring.

Closes #141

* refactor: use FTS5 bm25() column weights + exact match promotion

Replace Python-only post-processing with FTS5 bm25() column weights
(10x for symbol_name) combined with exact match promotion. Remove
_sort_key from SearchResult dataclass and _docstring_sort_key helper.
Add integration test reproducing the erpimage ranking bug from #141.
Guard against None values from database rows.
* feat: move widget config to YAML, add per-page instructions

- Add WidgetConfig model to CommunityConfig schema with title,
  initial_message, placeholder, and suggested_questions fields
- Add widget sections to all community YAML configs (hed, bids,
  eeglab, nemar) migrated from hardcoded frontend values
- Create GET /communities endpoint returning community metadata
  with widget config for frontend consumption
- Add widget_instructions field to PageContext for per-page
  customization (sent alongside page URL/title to backend)
- Update frontend demo page to fetch communities from API
  instead of hardcoding; setConfig() still works for overrides
- Add tests for WidgetConfig validation and /communities endpoint

Closes #152, closes #158

* fix: address PR review findings (XSS, prompt injection, error handling)

- Fix XSS: use DOM API instead of innerHTML for error display
- Add prompt injection guardrails for widget_instructions in system prompt
- Add error handling with logging in /communities endpoint
- Validate API response is array in frontend fetch
- Filter empty string widgetInstructions in widget JS
- Add tests for widget_instructions in API model and system prompt

* refactor: harden WidgetConfig with validation, frozen, and resolve()

- Add field validators: normalize empty strings to None, strip whitespace
- Add max_length constraints on title (100), initial_message (1000), placeholder (200)
- Validate suggested_questions: filter empties, cap at 10 entries
- Make WidgetConfig frozen (immutable after construction)
- Add resolve() method to consolidate defaulting logic
- Simplify /communities endpoint using resolve()
- Add 12 new tests for validation, immutability, and resolve()

* fix: make demo page embed examples dynamic from API

- Embed snippet on landing page now shows actual community IDs from API
- Configuration options list populated dynamically
- Added widgetInstructions to config options documentation
- Community-specific page shows widgetInstructions example in embed snippet

* fix: remove defensive try/except, simplify template literals

- Remove bare except in /communities; these are validated Pydantic
  models so serialization failures are code bugs, not transient errors
- Simplify dense template literal in embed example with pre-computed vars
- Remove unused logger import
@neuromechanist

Copy link
Copy Markdown
Member Author

Release PR #162 Review Summary

Ran 3 specialized review agents (code reviewer, silent failure hunter, test coverage analyzer) against the full develop->main diff (64 files, +9098/-617 lines).

CRITICAL (must fix before merge)

  1. Worker does not proxy /communities endpoint (code reviewer, 95% confidence)

    • frontend/index.html fetches ${API_BASE}/communities which hits the Cloudflare Worker
    • Worker has no route for /communities; it falls through to the community config regex, matches communityId = "communities", hits RESERVED_PATHS check, returns 404
    • Demo page will break in production -- no community cards will load
    • Fix: Add explicit route for /communities in the worker before the catch-all
  2. ask endpoint catches HTTPException and converts 403s to 500s (silent failure hunter)

    • src/api/routers/community.py:917-927: broad except Exception catches HTTPException(403) from authorization and converts to 500 "Internal server error"
    • The chat endpoint correctly has except HTTPException: raise (line 1023-1025) but ask does not
    • Fix: Add except HTTPException: raise before the broad except Exception
  3. Worker exposes raw error.message to clients (silent failure hunter)

    • workers/osa-worker/index.js:484-489: top-level catch returns error.message to users
    • Could leak internal URLs, env var names, or stack traces
    • Fix: Return generic error message, log the actual error
  4. Worker handleProtectedEndpoint has no JSON parse error handling (silent failure hunter)

    • workers/osa-worker/index.js:585: request.json() throws SyntaxError on malformed input
    • Propagates to top-level catch, exposes raw JS error message
    • Fix: Wrap in try-catch returning 400

IMPORTANT (should fix)

  1. NEMAR missing from worker root endpoint documentation (code reviewer)

    • workers/osa-worker/index.js:521: communities list says "hed, bids, eeglab" but not "nemar"
  2. Metrics DB init failure leaves app in degraded state with no health indication (silent failure hunter)

    • src/api/main.py:65-72: broad except Exception swallows init failure, health check still says "healthy"
  3. Plugin import failures silently degrade assistant capabilities (silent failure hunter)

    • src/assistants/community.py:275-278: failed plugin imports logged but assistant created without tools
  4. Community API key fallback silently charges platform key (silent failure hunter)

    • src/api/routers/community.py:486-501: missing env var falls back to platform key with only a log error
  5. /communities path not tested in metrics middleware (test coverage)

    • Could incorrectly extract "communities" as a community_id for sub-paths
  6. No API-level test for widget_instructions passthrough (test coverage)

    • Conversion from API PageContext to agent PageContext not integration-tested

SUGGESTIONS (nice to have)

  1. Overly broad CORS wildcard for .readthedocs.io (code reviewer)
  2. Rate limiter "fail open" with no alerting mechanism (silent failure hunter)
  3. Turnstile bypass when secret key missing in production (silent failure hunter)
  4. Broad except Exception in scheduler budget checks (silent failure hunter)
  5. NEMAR tools return error strings with overly broad catches (silent failure hunter)
  6. Metrics middleware has no failure counter (silent failure hunter)

What's Good

  • Generic community YAML tests automatically cover all 4 communities
  • WidgetConfig model thoroughly tested with validators, frozen, resolve()
  • Prompt injection guardrails for widget_instructions
  • NEMAR tools tested with real API calls (no mocks)
  • Scoped auth tests are clean end-to-end
  • Good error handling patterns throughout (logging with context, exception chaining)

- Add /communities route to worker (was returning 404, breaking demo page)
- Add except HTTPException: raise in ask endpoint (was converting 403s to 500s)
- Return generic error in worker top-level catch (was exposing error.message)
- Add JSON parse error handling in worker endpoints (return 400 not 500)
- Add NEMAR to worker root endpoint community list
- Add /communities to worker endpoint documentation
@neuromechanist

Copy link
Copy Markdown
Member Author

Review Fixes Applied (commit b91a555)

All 4 critical and 1 important issue addressed:

# Finding Fix
1 Worker missing /communities route (demo page would 404) Added explicit route before catch-all
2 ask endpoint converting 403s to 500s Added `except HTTPException: raise` matching chat endpoint
3 Worker exposing raw error.message to clients Return generic "Internal server error", log actual error
4 Worker JSON parse failures returning 500 Added try-catch in handleProtectedEndpoint and handleFeedback, returning 400
5 NEMAR missing from worker root docs Added to community list and endpoint docs

All 1352 tests pass, lint clean.

@github-actions

github-actions Bot commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

🚀 Preview Deployment

Name Link
Preview URL https://develop.osa-demo.pages.dev
Branch develop
Commit 48fef98

This preview will be updated automatically when you push new commits.

@neuromechanist neuromechanist merged commit 69d6022 into main Feb 7, 2026
18 checks passed
@neuromechanist neuromechanist deleted the develop branch February 7, 2026 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move widget suggested questions to community YAML config

1 participant