feat(kt-facts): DecompositionPipeline routes through registry-resolved provider (Phase 4 #44)#280
Conversation
…d provider (Phase 4 #44) Adds ``fact_decomposition_provider`` kwarg to ``DecompositionPipeline.__init__``. When set, ``extract_text`` builds a :class:`DecompositionContext` from the existing call-site args (concept / query_context / source_url → source_id, source_title → ``options``) and delegates to ``provider.decompose``. When ``None``, extraction falls back to the pipeline-owned ``TextExtractor`` (legacy path for callers not yet wired to the registry). ``kt_hatchet.composition`` gains ``resolve_fact_decomposition_provider``, a companion to ``resolve_phase_settings`` — workers call it at task entry to translate ``ctx.config.composition.fact_decomposition`` into a ready-to-inject provider instance via the plugin registry. Returns ``None`` on the legacy paths (no graph, no services, empty composition, no plugin registered) so callers fall back cleanly. ``decompose_chunk_task`` in worker-search is the first consumer — threads both resolvers into its ``DecompositionPipeline`` construction. Other DecompositionPipeline call sites (decompose_source_task, GatherFactsPipeline, building/unified / nodes/pipeline) still run the legacy TextExtractor path and follow in subsequent PRs. Tests: 2 new in ``test_pipeline_phase_settings.py`` pinning the provider-routing vs. fallback branches; 4 new in ``test_composition.py`` pinning the provider-resolver helper (happy-path / graph_id None / empty-composition / registry-miss). Builds on #279 (backend-engine-fact-decomposition plugin), stacked branch — rebase onto main after #279 merges. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three review items addressed: 1. ``DecompositionContext.source_title`` promoted to typed field on the ABC instead of side-channeled through ``options``. Pipeline + built-in adapter drop the options-bag hop. ABC now carries every legacy ``TextExtractor`` kwarg as a first-class field; ``options`` remains reserved for phase_settings-style per-graph knobs (model / thinking_level / batch_size) that land in Phase 4 follow-ups. Prevents other provider implementations from copying the pattern. 2. ``resolve_fact_decomposition_provider`` now logs a WARNING when a composition names a provider id no plugin contributes on this worker (rolling-deployment case). Was silent before — flagged as tension with fail-fast. Tolerant stance preserved (still returns ``None`` so caller falls back to legacy ``TextExtractor``) but the unresolved id no longer vanishes. Mirrors ``validate_all_graph_types`` canary policy. 3. Drop unused ``AsyncMock`` import in ``test_pipeline_phase_settings.py`` — ruff would flag. Test updates: - ``test_extract_text_routes_through_injected_provider`` now asserts ``ctx.source_title`` directly instead of ``ctx.options["source_title"]``. - ``test_fact_decomposition_provider_not_registered_warns_and_returns_none`` renamed + asserts WARN record present with graph_id + provider_id. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Review fixes pushed. Three issues addressed:
On remaining points:
Tests: 122 kt-core-engine-api + 7 facts + 9 composition + 5 plugin — all green. |
774e4b1
into
feat/backend-engine-fact-decomposition-plugin
|
I have read the CLA Document and I hereby sign the CLA You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot. |
Summary
Consumer-side wire-up for Phase 4. `DecompositionPipeline` now accepts an optional `fact_decomposition_provider` kwarg; `extract_text` routes through `provider.decompose` when one is injected, else falls back to the pipeline-owned `TextExtractor`.
`kt_hatchet.composition` gains `resolve_fact_decomposition_provider` — companion to `resolve_phase_settings`. Workers call both at task entry to translate `ctx.config.composition.fact_decomposition` into a ready-to-inject provider instance via the plugin registry.
`decompose_chunk_task` in worker-search is the first consumer. Other call sites (`decompose_source_task`, `GatherFactsPipeline`, `building/unified`, `nodes/pipeline`) still run legacy `TextExtractor` — they follow in subsequent PRs once this proves the shape.
Why
Closes the consumer half of Phase 4 #44 — ABC + plugin + pipeline integration all present, first worker wired. Demonstrates the full round-trip: `composition.fact_decomposition` id → plugin registry lookup → `FactDecompositionProvider` instance → pipeline routes extraction through it.
Based on #279 (adds `backend-engine-fact-decomposition` plugin contributing `llm-default`). Rebase onto main after #279 merges.
Test plan
🤖 Generated with Claude Code