feat(preflight): replace SUPPORTED_RUNTIMES static list with adapter discovery - #2155
Merged
Merged
Conversation
…discovery Closes task #123 — last piece of #87 cleanup. Pre-fix: workspace/preflight.py:11 hardcoded a tuple of "supported" runtime names (claude-code, codex, ollama, langgraph, etc.). Every new template repo required a code change in molecule-runtime to be recognized — direct violation of the universal-runtime principle (#87) where adapters declare themselves and the runtime stays generic. Post-fix: discovery-based validation via the same ADAPTER_MODULE env var that production load paths already consult (workspace/adapters/__init__.py:get_adapter). Distinguished failure modes so operator messages are concrete: - ADAPTER_MODULE unset → "no adapter installed; set the env var" - ADAPTER_MODULE set but module won't import → import error type + message - module imports but no Adapter class → "convention violation, add `Adapter = YourClass`" - Adapter.name() raises → caught with operator message - Adapter.name() returns non-string → contract violation message - Adapter.name() doesn't match config.runtime → drift WARNING (not fatal; the adapter wins in production, config.yaml is just documentation) The drift case is the one behavioral change worth calling out: the prior static-list path would have hard-failed config.runtime values not in the allowlist. With discovery, an unknown runtime in config.yaml is just a documentation drift — the adapter that's actually installed runs regardless. Operator gets a warning naming both the configured and installed names so they can fix whichever is stale. Tests: - Replaces the obsolete "static list pass/fail" tests with 6 new cases covering each distinguished failure mode, plus a positive test for the adapter-matches-config happy path - Adds an autouse `_default_langgraph_adapter` fixture that pre-installs a fake adapter via sys.modules monkey-patching, so existing tests building default WorkspaceConfig (runtime="langgraph") inherit a valid adapter without each test setting ADAPTER_MODULE - Failure-mode tests opt out of the default fixture via @pytest.mark.no_default_adapter (registered in pytest.ini) - Sentinel pattern (`_UNSET = object()`) for `name_returns` so None is a passable test value (otherwise `is not None` would skip the None branch — exact bug the sentinel avoids) Verification: - 22/22 preflight tests pass (was 16; +6 new failure-path tests) - 1256/1256 workspace pytest pass (was 1251; +5 net) - No production code path other than preflight changed Source: 2026-04-27 #87 cleanup audit after PR #2154 (wedge extraction). This change is independent of the cli_executor.py template moves (task #122) — completes one of the two remaining cleanup items. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HongmingWang-Rabbit
requested a review
from hongmingwang-moleculeai
as a code owner
April 27, 2026 07:45
HongmingWang-Rabbit
enabled auto-merge
April 27, 2026 07:45
Contributor
Author
Code review (5-axis) — needs cross-account approval
Correctness: ✓
Tests: ✓
Architecture: ✓
Security: ✓
Performance: ✓ — preflight runs once at startup; one module import is negligible Nit: Verdict: would approve. Auto-merge already armed; will fire once CI greens + an approving review lands. |
1 task
3 tasks
HongmingWang-Rabbit
pushed a commit
that referenced
this pull request
Jun 12, 2026
… redis online-status key/TTL coverage (#2150) Refile of the WIP at origin/regression/2150-migration-replay-from-scratch-real-pg (stalled 2026-06-03, never advanced past DRAFT, base on a 200-commit-stale main that would have undone my PR #2449's guard widening + the mc#1982 mask removal + the #2149 scheduler trigger if merged directly). This is the #2150 implementation (close-supersedes the WIP PR #2155): - workspace-server/internal/db/postgres_replay_integration_test.go (286 lines) Real-PG integration tests for db.RunMigrations (forward chain replay-from- scratch via the production entrypoint, hard-fail; double-apply for the 045 crash-loop class) and db.InitPostgres (ping + bad-DSN). - workspace-server/internal/db/redis_test.go (291 lines) Unit tests for redis.go (was untested fleet-wide): SetOnline / IsOnline / RefreshTTL on ws:<id>, CacheURL / GetCachedURL on ws:<id>:url, internal namespace pin, LivenessTTL >= 5x heartbeat, real TTL expiry via miniredis. - .gitea/workflows/handlers-postgres-integration.yml (+27) New 'Migration replay-from-scratch gate (#2150)' step, runs the integration suite against a SEPARATE 'molecule_replay' database on the same sibling Postgres (so the destructive DROP SCHEMA never touches the handlers molecule DB). Inserted AFTER the scheduler (#2149) step; does NOT undo any of: the mc#1982 mask removal, the preflight INTEGRATION_DB_URL check, or the table-presence guard widening (PR #2449). - .gitea/scripts/detect-changes.py (+5) 'handlers-postgres' profile now also matches internal/db/ (additive, preserves the scheduler trigger from #2149) so a change to redis.go or postgres.go runs the gate. Refs #2150. Supersedes the WIP PR #2155 (DRAFT, 6 days stalled, branched from a 200-commit-stale main).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes task #123 — last piece of #87 cleanup independent of the cli_executor.py template moves.
Pre-fix:
workspace/preflight.py:11hardcoded a tuple of "supported" runtime names. Every new template repo required a code change in molecule-runtime to be recognized — direct violation of the universal-runtime principle (#87).Post-fix: discovery-based validation via the same `ADAPTER_MODULE` env var that production load paths already use (`workspace/adapters/init.py:get_adapter`). Distinguished failure modes so operator messages are concrete:
Adapter = YourClassper BaseAdapter convention"Behavioral change worth calling out
The drift case is a softening: prior static-list path hard-failed config.runtime values not in the allowlist; now drift is a warning so the workspace still boots while operator gets actionable info naming both the configured + installed runtime names. Reflects production reality (the adapter wins regardless).
Tests (6 new + autouse fixture)
Verification
🤖 Generated with Claude Code