Skip to content

Release 0.7.0#218

Merged
neuromechanist merged 28 commits intomainfrom
develop
Feb 25, 2026
Merged

Release 0.7.0#218
neuromechanist merged 28 commits intomainfrom
develop

Conversation

@neuromechanist
Copy link
Member

@neuromechanist neuromechanist commented Feb 19, 2026

Summary

Release 0.7.0 merges develop into main, covering all features and fixes since 0.6.7.

Features

Fixes

Infrastructure

  • CI workflow to notify documentation repo on push to main
  • Dockerfile and deployment architecture updates

Test plan

  • All tests pass on develop
  • CI passes on this PR
  • Version auto-stripped to 0.7.0 on main by CI
  • Deploy to prod after merge

neuromechanist and others added 21 commits February 13, 2026 09:26
Add Open Graph and Twitter Card meta tags so sharing
links on Slack, Discord, Twitter, etc. shows a proper
preview card with the OSA branding image from osc.earth.
- Inline SVG OSA logo in header (uses currentColor for
  dark mode compatibility)
- Dark mode CSS via prefers-color-scheme on demo page
- Footer with dynamic year, heart, and OSC link
- Consistent deep blue color palette across both pages
- Add dark mode to dashboard (matching frontend theme)
- Add <meta name="description"> to both pages for SEO
- Remove redundant twitter:title/description/image tags
- Fix broken GitHub links (osc-em -> OpenScience-Collective)
- Standardize org name to "OpenScience Collective"
- Move dashboard inline styles to CSS classes
- Rename .footer to .site-footer for consistency
* Enforce mandatory HED tag validation before display

Fixes #210

* Address review: consistent error handling, sanitize exceptions
)

* Fix sync status page: N/A display, all sync types, community-aware

Fixes #212

- Fix Papers Sync showing N/A: sync_metadata stores source names like
  "openalex:query", not "openalex", so use prefix matching to find the
  most recent timestamp for each source type
- Make /sync/status community-aware: accept community_id query param and
  query the correct community database (previously always used hed default)
- Add all sync types to response: new 'syncs' field includes github,
  papers, docstrings, mailman, beps, faq with last_sync and next_run
- Dashboard: pass community_id to sync status fetch, render all sync
  types dynamically including next scheduled run time

* Address review findings: validation, future times, health endpoint

- Validate community_id against registry (404 for unknown)
- Update /sync/health to accept community_id param
- Fix formatRelativeTime to handle future timestamps (next_run)
- Use _parse_iso_datetime in _get_most_recent_sync for robust comparison
- Fix misleading citing_doi comment in papers source lookup
- Add exc_info=True to warning log calls for full tracebacks
- Add tests: prefix matching regression, syncs field, unknown community 404

* Fix test: add isolated_db fixture to community_id test
- Fix papers last_sync timestamp comparison: use _parse_iso_datetime
  instead of string max() to avoid wrong result with mixed UTC offsets
- Fix dashboard /sync/health URL: pass community_id param so health
  badge reflects the viewed community, not always 'hed'
- Add tests for /sync/health community_id param: 404 for unknown,
  200 for known community
- Add exc_info=True to trigger_sync error log for full tracebacks
- Upgrade scheduler job inspection failure from warning to error
* Refactor CLI to thin client architecture (#215)

Split heavy monolithic CLI into lightweight HTTP client (7 core deps)
with optional [server] group for backend commands. Default API URL
changed to https://api.osc.earth/osa. Add init/ask/chat commands,
YAML config with credentials split, SSE streaming, BYOK headers.
Server commands (serve/sync/validate) gated behind ImportError.

Closes #215

* Address PR review findings

- Fix TOCTOU race in save_credentials: use os.open with 0o600 mode
- Add markup=False to print_error hint output
- Replace fragile type-name string matching with specific httpx exceptions
- Fix chat loop: catch httpx errors instead of broad Exception
- Extract _stream_request to deduplicate SSE parsing in client
- Skip old default localhost URL during legacy config migration
- Fix misleading docstrings (_handle_response, ask, test_client)
- Remove unused print_table from output module

* Fix ANSI escape codes breaking help text assertions in CI

Rich inserts color codes that split '--assistant' into separate
tokens. Use click.unstyle() to strip ANSI before asserting.

* Bump version to 0.7.0.dev0 for thin client refactor

* Remove ExecutionConfig and standalone mode

The CLI is a thin HTTP client only. Local agent execution
is not supported; all queries go through the remote API.

* Address final review findings

- Move pydantic-settings to [server] optional deps (unused by thin client)
- Use Literal type for OutputConfig.format instead of plain str
- Add ValidationError to config/credentials load exception handlers
- Fix dead code path in _ask_batch (AskResponse has no "message" field)
- Replace behavioral mock with real file setup in health test
security.py used X-OpenRouter-API-Key but community router,
widget, worker, and docs all use X-OpenRouter-Key. Aligned
security.py to canonical name. Client sends both headers for
backward compatibility with servers not yet updated.
- README: Fix CLI syntax (osa ask -a hed), add osa init, note
  server deps requirement for osa serve
- DEPLOYMENT_ARCHITECTURE: Fix BYOK header name to X-OpenRouter-Key,
  update CLI commands, remove standalone mode references
- local-testing-guide: Fix CLI flags (--community/--standalone removed)
Code simplification:
- Extract _get() helper and _chat_payload() static method in client.py
- Simplify legacy migration with dict comprehension
- Extract patched_config_paths fixture to reduce test boilerplate

Error handling fixes:
- Narrow broad except Exception to specific httpx exceptions in
  init and health commands
- Add stub commands for sync/validate when server deps missing
  (instead of silently hiding commands)
- Add debug logging for malformed SSE data lines
Dispatches a repository_dispatch event to the documentation repo
so it can auto-update the OSA submodule and open a sync PR.
Requires DOCS_REPO_TOKEN secret (fine-grained PAT with Contents
read/write on the documentation repo).
* Surface community config health via public API

Downgrade noisy API key warning from error to debug level
in discover_assistants() so it stops spamming CLI users.

Extract compute_community_health() helper in health.py and
add config_health to GET /{community_id}/metrics/public and
status field to GET /{community_id}/ config response.

Warnings clearly communicate that using the shared platform
key is for demonstration only and not sustainable.

Closes #220

* Address PR review: fix error handling and security

- Move compute_community_health() call inside try/except in
  get_communities_health() to restore error containment
- Add try/except around health computation in config and
  public metrics endpoints so failures don't crash them
- Sanitize warnings for public endpoint: strip env var names
  to prevent information disclosure
- Change logger.debug to logger.warning in discover_assistants
  so operators see missing key warnings at startup
- Move inline imports to top-level (no circular import risk)
- Remove redundant "error" key from fallback dict

* Fix CI: initialize temp metrics DB in health status tests

The public metrics tests need a metrics DB to avoid 503.
Use the same tmp_path + patch pattern as test_metrics_public.
Display config_health data from /metrics/public API on the
frontend status page. Shows orange banner for degraded status
(using platform key) and red banner for error status (missing
API key). Part of issue #220.
Communities without openrouter_api_key_env_var configured were
silently using the platform key with no warning. Now all
communities without a dedicated API key show a warning on the
status dashboard.
* Add community-specific logos to chat widget (#224)

Support custom logos in widget header avatar with three-tier
precedence: widget JS setConfig override, YAML logo_url field,
and convention-based logo file detection in community folders.

* Address PR review findings

- Add CSP header for SVG responses to prevent XSS
- Add onerror fallback on img to restore brain icon
- Wrap _find_logo_file in OSError handling
- Add URL scheme validator on logo_url field
- Rename to find_logo_file (public API, no underscore)
- Extract convention_logo_url helper to deduplicate
- Remove redundant _LOGO_EXTENSIONS constant
- Fix docstrings: "Override" -> "Fallback", file list
- Fix comment: "relative" -> "path-only"
- Add TOCTOU guard in /logo endpoint
- Set explicit filename in FileResponse
* Add FieldTrip community, generalize docstring/FAQ tools

- Add FieldTrip EEG community config with 30+ docs, docstrings,
  citations, widget theme color (#008a79), and sync schedules
- Wire up _build_tools() to auto-generate docstring and FAQ tools
  from community config (include_docstrings, include_faq)
- Add sqlite3.OperationalError handling to generic tool factories
- Migrate EEGLAB from custom tools.py to generic factory
- Add theme_color support to WidgetConfig model and frontend widget
- Update EEGLAB integration tests for generic factory tools

Closes #225

* Address PR review findings

- Narrow OperationalError catch to "no such table" only; re-raise
  infrastructure errors (corruption, disk full, permissions)
- Add structured logging context (query, community) to warnings
- Remove duplicate theme color block in applyWidgetConfig()
- Add hex color regex validation before parseInt in widget JS
- Add mailman check to has_faq condition for precision

* Add tests for review findings and fix issues

- Add tests for OperationalError handling (missing table scenario)
- Add tests for create_knowledge_tools with docstrings/FAQ flags
- Add tests for WidgetConfig theme_color validation and resolve()
- Add docstring/FAQ tool checks to generic community test suite
- Narrow OperationalError catch to "no such table" only
- Add hex color regex validation in widget JS
- Remove duplicate theme color block in applyWidgetConfig()
- Tighten has_faq condition to require mailman config
@neuromechanist neuromechanist changed the title Release 0.7.0: Thin client CLI architecture Release 0.7.0 Feb 25, 2026
- Add logging to silent except blocks in CLI config/credentials
  loading so failures are visible to users and operators
- Log credential permission fallbacks with security warnings
- Upgrade SSE malformed event log from debug to warning level
- Narrow bare except Exception to specific types in health
  computation and LangFuse tracing setup
- Restore structured extra={} dict in env var warning log
- Add logo feature tests: URL validator, find_logo_file,
  convention_logo_url, /logo endpoint (CSP, 404, media types),
  resolve() fallback precedence
@neuromechanist
Copy link
Member Author

Release 0.7.0 PR Review Summary

Ran 3 review agents: code-reviewer, silent-failure-hunter, test-analyzer.

Code-Reviewer: Clean for merge

No integration-level issues found. Individual features compose correctly, BYOK header migration is consistent, no credentials exposed.

Silent-Failure-Hunter: 4 Critical, 4 High, 3 Medium

All addressed in PR #228 (merged to develop):

  • C1-C2: Added logger.warning to silent config/credentials loading failures
  • C3: Added logging for credential file permission fallbacks (security)
  • C4: Upgraded SSE malformed event log from debug to warning
  • H1-H2: Narrowed except Exception to specific types in health computation
  • H3: Narrowed except Exception in LangFuse tracing setup
  • H4: Restored structured extra={} dict in env var warning log

Test-Analyzer: 3 Critical Gaps

All addressed in PR #228:

  • T1: Added 4 tests for find_logo_file + 3 for convention_logo_url
  • T2: Added 12 tests for logo_url validator (XSS prevention via scheme validation)
  • T3: Added 4 tests for /logo endpoint (SVG CSP header, 404, media types) + 1 for API response

Result

@github-actions
Copy link
Contributor

github-actions bot commented Feb 25, 2026

Preview Deployment

Name Link
Preview URL https://develop-demo.osc.earth
Branch develop
Commit 4dc0f94

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

@github-actions
Copy link
Contributor

github-actions bot commented Feb 25, 2026

Dashboard Preview

Name Link
Preview URL https://develop.osa-dash.pages.dev
Branch develop
Commit 4dc0f94

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

* feat: onboard MNE-Python community with Discourse syncer

Add MNE-Python as a new community with 31 documentation pages,
5 GitHub repos, 5 citation DOIs, Python docstring extraction,
and Discourse forum sync. Build a generic Discourse syncer using
the public JSON API with patient rate limiting (1 req/s).

Key changes:
- MNE community config (config.yaml) with full ecosystem
- Generic Discourse syncer (discourse_sync.py) with incremental sync
- DB schema: discourse_topics table with FTS5 search
- HTML-to-markdown auto-conversion in doc fetcher (for Sphinx docs)
- Discourse search tool factory and CLI sync command
- DiscourseCategoryConfig and SyncConfig.discourse schema additions
- Tests for DB, search, config validation, and live API

Closes #229

* fix: address PR review findings for Discourse syncer

- Wrap per-topic sync loop in try/except to prevent single
  bad topic from crashing the entire sync
- Use .get() for topic id/slug to avoid KeyError on malformed
  API responses
- Add logging when listing pagination fails
- Move get_last_sync to top-level import
- Include discourse count in sync_all total_items summary
- Remove redundant snippet truncation in discourse tool

* Add missing tests for discourse tools and helpers

- TestSearchDiscourseTool: missing table, no results, correct naming
- TestHtmlToText: simple HTML, empty input, code blocks, whitespace
- TestGetAcceptedAnswer: accepted answer, fallback to liked, no replies
- Updated test_includes_all_optional_tools to include discourse

* Fix comment accuracy issues from review

- Rename _html_to_text to _html_to_markdown (matches actual behavior)
- Fix _get_accepted_answer docstring: "most-liked" not "highest-scoring"
- Update get_last_sync/update_sync_metadata docs to include 'discourse'

* Improve type safety for Discourse category config

- Use DiscourseCategoryConfig directly instead of list[dict]
- Remove model_dump() type laundering in sync.py
- Add field validation: slug pattern, id >= 1
- Change accepted_answer_snippet to str | None
@github-actions
Copy link
Contributor

github-actions bot commented Feb 25, 2026

⚠️ Worker Deployment Required

This PR modifies community CORS origins. Worker changes detected. After merging to main or develop, the workflow will automatically deploy the worker.

Manual deployment (if needed):

cd workers/osa-worker
wrangler deploy --env dev  # for develop branch
wrangler deploy            # for main branch

neuromechanist and others added 2 commits February 25, 2026 04:43
Not yet onboarded by their maintainers; only hosted on
demo.osc.earth for now. Left TODO comments for maintainers
to submit PRs when ready.
@neuromechanist
Copy link
Member Author

Release 0.7.0 - PR Review Summary

Reviewed with 3 specialized agents: code-reviewer, silent-failure-hunter, pr-test-analyzer.

Critical Issues: 0

High Priority (non-blocking, defensive improvements)

  1. SSE stream silently skips malformed data (src/cli/client.py) -- If server returns non-JSON SSE data, user gets empty response. Could add consecutive failure threshold.
  2. Discourse sync bare except Exception (src/knowledge/discourse_sync.py) -- Catches everything including programming bugs. Could narrow catch scope and add early-exit on systematic failures.

Medium Priority (8 items)

  • Silent user ID regeneration/save failure (no logging) in cli/config.py
  • Retry-After header parsed as int without try/except in discourse_sync.py
  • compute_community_health catches AttributeError which could mask bugs
  • API key warning downgraded from error to warning
  • ISO timestamp string comparison in incremental sync (works but fragile)
  • Sync status defaults to 'hed' silently when no community_id
  • sync_all Discourse section uses bare except Exception

Test Gaps (non-blocking)

  • No tests for _html_to_markdown/_is_html in fetcher.py (9/10 criticality)
  • No dedicated FieldTrip config validation tests (8/10)
  • No tests for CLI streaming/SSE methods (7/10)

Strengths

  • Security well-implemented (credential permissions, SVG CSP headers, BYOK backward compat)
  • Knowledge tool factories handle missing DB tables gracefully
  • Logo endpoint tests excellent
  • CLI error handling significantly improved
  • Discourse syncer well-tested at DB layer

Verdict

No critical issues. High-priority items are defensive edge-case improvements, not production blockers. Release is ready to merge.

@neuromechanist neuromechanist merged commit 4eb0cd3 into main Feb 25, 2026
1 check passed
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.

1 participant