molecule-core/workspace
Hongming Wang 4f4b6c4f90 test(runtime): pin PR #2756's card-vs-setup decoupling with build_routes helper
PR #2756's contract — card route always mounted regardless of
adapter.setup() outcome — lived inline in main.py's `# pragma: no cover`
boot sequence. A future refactor that re-coupled the two would have
silently bypassed PR #2756 and shipped the original "stuck booting
forever" UX again, with no pytest catching it.

This change extracts route assembly into workspace/boot_routes.py's
build_routes(card, executor, adapter_error) and pins the contract with
6 integration tests using Starlette's TestClient:

- test_card_route_serves_200_when_adapter_ready: happy path
- test_card_route_serves_200_when_adapter_failed: misconfigured boot,
  card still 200, skill stubs survive
- test_jsonrpc_returns_503_when_no_executor: full -32603 envelope with
  the adapter_error in error.data
- test_jsonrpc_returns_503_with_generic_when_no_error_string: fallback
  reason for the rare case main.py reaches this branch without one
- test_card_route_does_not_depend_on_executor: direct PR #2756
  regression guard — both branches MUST mount the card route
- test_executor_present_does_not_mount_not_configured_handler: sanity
  that a healthy workspace doesn't return -32603 to every request

Conftest stubs extended with a2a.server.routes / request_handlers
classes so the tests work under the existing a2a-mock infra (pattern
matches the AgentCard/AgentSkill stubs added for PR #2765).

main.py now calls build_routes; the inline if/else is gone. Same
production behaviour, cleaner shape, regression-proof.

Heavy a2a-sdk imports inside build_routes() are lazy (deferred to the
executor-only branch) so tests that only exercise the not-configured
path don't pull DefaultRequestHandler / InMemoryTaskStore.

card_helpers + boot_routes registered in TOP_LEVEL_MODULES (build
drift gate would have caught the missing entry on the wheel-publish
smoke).

All 18 related tests pass (test_boot_routes.py: 6, test_card_helpers.py:
6, test_not_configured_handler.py: 6).

Closes #2761
Pairs with: PR #2756 (decouple agent-card from setup),
            PR #2765 (defensive isolation of enrichment + transcript)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 14:59:56 -07:00
..
adapters fix: comprehensive a2a-sdk 1.x migration sweep across workspace/ 2026-04-27 09:42:57 -07:00
builtin_tools feat(harness): coordinator phase-boundary instrumentation for RFC #2251 2026-04-28 20:11:46 -07:00
lib feat(workspace): pre-stop serialization for pause/resume (closes #1386) 2026-04-21 12:40:44 +00:00
molecule_audit chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
platform_tools feat(mcp): multi-workspace routing for memory + chat_history + workspace_info 2026-05-04 14:17:58 -07:00
plugins_registry feat(plugin): implement MCPServerAdaptor (issue #847) 2026-04-24 01:42:13 +00:00
policies feat(platform): single-source-of-truth tool registry — adapters consume, no drift 2026-04-28 17:11:36 -07:00
scripts fix(git-token-helper): close TOCTOU window + stop swallowing chmod errors (closes #1552) 2026-04-26 08:22:29 -07:00
skill_loader feat(skills): per-skill runtime compatibility (#119, hermes pattern) 2026-04-27 01:57:43 -07:00
tests test(runtime): pin PR #2756's card-vs-setup decoupling with build_routes helper 2026-05-04 14:59:56 -07:00
.coveragerc test(workspace): centralize pytest-cov config + 92% floor (closes #1817) 2026-04-26 06:21:22 -07:00
a2a_cli.py fix(runtime): use lowercase wire role for v0.3 JSON-RPC compat layer 2026-04-27 12:40:11 -07:00
a2a_client.py feat(mcp): multi-workspace routing for memory + chat_history + workspace_info 2026-05-04 14:17:58 -07:00
a2a_executor.py fix(a2a): route terminal Message via TaskUpdater.complete/failed in task mode 2026-05-03 04:06:45 -07:00
a2a_mcp_server.py fix(mcp): wire source_workspace_id through dispatcher for memory + chat_history + workspace_info 2026-05-04 14:41:24 -07:00
a2a_tools.py feat(mcp): multi-workspace routing for memory + chat_history + workspace_info 2026-05-04 14:17:58 -07:00
adapter_base.py feat(workspace): wire EventLog into adapter base (#119 PR-3b) 2026-05-03 01:18:19 -07:00
agent.py chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
agents_md.py chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
boot_routes.py test(runtime): pin PR #2756's card-vs-setup decoupling with build_routes helper 2026-05-04 14:59:56 -07:00
build-all.sh fix: update workspace script comments for workspace-template → workspace rename 2026-04-18 01:48:05 -07:00
card_helpers.py fix(runtime): isolate card-skill enrichment + transcript handler from adapter shape mismatch 2026-05-04 14:15:27 -07:00
config.py feat(workspace): event_log module + EventLogConfig (#119 PR-2) 2026-05-03 00:17:12 -07:00
configs_dir.py fix(runtime): auto-fallback CONFIGS_DIR for non-container hosts (closes #2458) 2026-05-01 13:07:55 -07:00
consolidation.py fix: apply #1124 env-var defaults + scrub F1088 credentials from INCIDENT_LOG.md (#1347) 2026-04-21 08:11:44 +00:00
coordinator.py feat(harness): coordinator phase-boundary instrumentation for RFC #2251 2026-04-28 20:11:46 -07:00
Dockerfile feat(workspace): 45-min gh-token refresh daemon + credential helper cache 2026-04-22 19:52:46 -07:00
entrypoint.sh fix(workspace): credential helper security hardening (#1797) 2026-04-23 18:14:55 +00:00
event_log.py feat(workspace): event_log module + EventLogConfig (#119 PR-2) 2026-05-03 00:17:12 -07:00
events.py chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
executor_helpers.py docs(a2a): correct misleading v1-tolerance comments 2026-05-02 02:33:00 -07:00
heartbeat.py feat(workspace): wire observability config into heartbeat + uvicorn (#119 PR-3a) 2026-05-03 01:01:57 -07:00
inbox.py mcp: support multi-workspace external-agent registration (PR-1) 2026-05-04 08:06:00 -07:00
initial_prompt.py chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
internal_chat_uploads.py fix(workspace): surface errno + path on chat-upload mkdir failure 2026-05-01 11:47:53 -07:00
internal_file_read.py feat(chat_files): rewrite Download as HTTP-forward (RFC #2312, PR-D) 2026-04-29 15:19:02 -07:00
main.py test(runtime): pin PR #2756's card-vs-setup decoupling with build_routes helper 2026-05-04 14:59:56 -07:00
mcp_cli.py fix: bot-lint nits — drop unused imports, add reason to except 2026-05-04 08:16:12 -07:00
molecule_ai_status.py fix(runtime): replace remaining /app/ legacy paths in agent prompts + docstrings 2026-04-27 11:22:00 -07:00
not_configured_handler.py fix(runtime): decouple agent-card readiness from adapter.setup() 2026-05-04 10:22:31 -07:00
platform_auth.py feat(mcp): cross-workspace delegation routing (multi-ws PR-2) 2026-05-04 08:32:24 -07:00
platform_inbound_auth.py fix(runtime): auto-fallback CONFIGS_DIR for non-container hosts (closes #2458) 2026-05-01 13:07:55 -07:00
plugins.py chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
preflight.py fix(preflight): downgrade required_env + auth_token failures to warnings 2026-05-04 12:20:34 -07:00
prompt.py feat(prompt): Platform Capabilities preamble at top of system prompt 2026-04-29 21:31:13 -07:00
pytest.ini feat(preflight): replace SUPPORTED_RUNTIMES static list with adapter discovery 2026-04-27 00:44:51 -07:00
rebuild-runtime-images.sh fix: update workspace script comments for workspace-template → workspace rename 2026-04-18 01:48:05 -07:00
requirements.txt chore(deps)(deps): update starlette requirement in /workspace 2026-05-03 01:36:45 +00:00
runtime_wedge.py chore(workspace): drop claude_sdk_executor — Phase 2 of #87 2026-04-27 00:52:55 -07:00
shared_runtime.py feat(platform): single-source-of-truth tool registry — adapters consume, no drift 2026-04-28 17:11:36 -07:00
smoke_mode.py chore(smoke): runtime_wedge follow-ups from PR #2473 review 2026-05-01 18:01:51 -07:00
transcript_auth.py chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00
watcher.py chore: open-source restructure — rename dirs, remove internal files, scrub secrets 2026-04-18 00:24:44 -07:00