Skip to content

feat(schemas): dynamic schema enrichment lifecycle (#274)#305

Merged
tikazyq merged 1 commit into
mainfrom
claude/implement-issue-274-vpNAh
May 20, 2026
Merged

feat(schemas): dynamic schema enrichment lifecycle (#274)#305
tikazyq merged 1 commit into
mainfrom
claude/implement-issue-274-vpNAh

Conversation

@tikazyq
Copy link
Copy Markdown
Contributor

@tikazyq tikazyq commented May 20, 2026

Closes #274

Summary

Formalises the resolve_schema() lifecycle so long-running processes don't pay the schema-enrichment network round-trip on every request, and so offline / bad-token sessions degrade gracefully instead of aborting.

  • core: new AdapterCache (TTL-keyed by project root) — get_or_resolve, refresh, invalidate, clear. resolve_inline failures inside AdapterRegistry::create are now warnings on stderr; the CLI falls back to the static schema instead of refusing to run.
  • http: AppState carries the shared Arc<AdapterCache>. Spec / adapter / schema handlers route through resolve_adapter_cached. New POST /api/projects/{id}/schema/refresh flushes a project's cache entry and returns the freshly-resolved schema.
  • mcp: ServerState holds the adapter behind a RwLock<Arc<dyn Adapter>> so the new reload_schema tool can swap in a freshly-resolved adapter without restarting the server.
  • cli: leanspec capabilities --refresh (informational on the single-shot CLI; surfaces enrichment errors loudly when present).

Provider impact

Touches the adapter seam. The Adapter trait surface is unchanged; what changed is how callers hold the resolved adapter:

Before After
Box<dyn Adapter> returned by resolve_adapter everywhere HTTP handlers receive Arc<dyn Adapter> from resolve_adapter_cached (shared, re-usable); MCP keeps ServerState::adapter() returning a snapshot Arc<dyn Adapter>; CLI still gets Box<dyn Adapter> (single-shot, no cache benefit).
resolve_inline errors in AdapterRegistry::create were fatal Errors emit warning: could not enrich <adapter> schema (…). Using static defaults. on stderr and the adapter falls back to its declared defaults.

No serialized format / public-API breakage; UI / agents that already call GET /api/projects/{id}/schema keep working unchanged.

Test plan

  • cargo test --all-features (all suites green, including new AdapterCache unit tests, HTTP schema/refresh integration tests, and MCP reload_schema dispatch test)
  • cargo clippy --all-features --all-targets -- -D warnings
  • cargo fmt --check
  • Cache: TTL expiry, invalidate, refresh, clear, multi-project isolation
  • HTTP: schema refresh returns fresh payload; unknown-project 404; back-to-back GETs return identical schemas (cache hit)
  • MCP: reload_schema tool advertised in tools/list and dispatchable
  • Manual: leanspec capabilities --refresh on a GitHub-configured project (left for follow-up — requires a real GitHub token; covered by the existing create_github_adapter_resolves_labels mockito test).

Delivers

From the Plan in #274:

  • Define resolve_schema() lifecycle in AdapterRegistry::from_project() (treat errors as warnings)
  • Add AdapterRegistry instance cache for long-running processes (AdapterCache with TTL, default 5 minutes)
  • HTTP server: cached adapter resolution
  • HTTP server: POST /api/projects/{id}/schema/refresh
  • MCP server: reload_schema tool
  • CLI: --refresh flag on capabilities
  • Document enrichment behavior (CHANGELOG entry)

Note: the spec's example output of "(14 options)" after enum field lines is not yet rendered by the capabilities command — the resolved options are already shown in the existing enum [open, closed] form, so the missing piece is purely cosmetic and was deferred to keep this PR focused on the lifecycle / caching mechanics.


Generated by Claude Code

Wire AdapterCache into long-running processes so network-backed schema
enrichment (GitHub labels, ADO states, Jira statuses) is baked once per
project and re-used across requests instead of being re-fetched on every
hit. Adapter enrichment failures now warn on stderr and fall through to
the static schema defaults, letting offline / bad-token sessions still
work.

- core: new AdapterCache with TTL, invalidate, refresh, clear
- core: resolve_inline failures warn instead of aborting
- http: AppState carries the shared cache; spec / adapter / schema
  handlers route through resolve_adapter_cached
- http: POST /api/projects/{id}/schema/refresh flushes a project's
  cache entry and returns the freshly-resolved schema
- mcp: ServerState holds the adapter behind a RwLock so reload_schema
  can swap in a freshly-resolved adapter without restart
- mcp: new reload_schema tool
- cli: capabilities accepts --refresh (informational, single-shot)
Copilot AI review requested due to automatic review settings May 20, 2026 03:03
@tikazyq tikazyq merged commit 25853fb into main May 20, 2026
1 check failed
@tikazyq tikazyq deleted the claude/implement-issue-274-vpNAh branch May 20, 2026 03:06
@tikazyq tikazyq review requested due to automatic review settings May 20, 2026 03:25
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.

spec(schemas): Dynamic Schema Enrichment

2 participants