Files
Lore Engine Dev b8b370b94a slice 5T.4: TemplateRegistry + dynamic tool generator
Templates module (package init) and the runtime registry:

* TemplateRegistry
  - .reload() rescans templates_dir and rebuilds the
    {template_id: TemplateSpec} dict atomically
  - .query(template_id, qid, args, graph) dispatches to the
    graph backend via query_cypher()
  - Duplicate template ids in the same dir raise
    TemplateRegistryError with both source paths
  - Every loaded query is re-validated through the Cypher
    allowlist, so a bad body never reaches a backend
  - Coerces string-typed optional params the same way the
    core tools do ("null" / "None" / "" -> None)

* dynamic_tools.build_dynamic_tools(registry)
  - One MCP ToolEntry per declared query: name = query.id,
    description = query.description, inputSchema derived
    from parameters (required = non-optional names).
  - One list_template_tools discovery entry that returns
    {templates: [{id, queries: [...]}, ...]} and accepts
    an optional template_id filter.
  - Same _make_adapter shape as the core tools so the
    existing MCPServer dispatcher serves them with no
    changes.

* 15 dedicated tests in test_template_registry.py cover:
  empty dir, single template, query dispatch, duplicate-id
  rejection, reload invalidates cache, dynamic tool schema
  shape, list_template_tools (with and without filter),
  merge into TOOL_REGISTRY visible in tools/list, end-to-end
  tool call (with and without rows), missing required param
  yields [], unknown template id / query id raise, and the
  defining test: drop a new template file, reload(), see a
  new tool appear with no code change.

Suite: 685 -> 700 (+15).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-19 02:29:14 -04:00
..