fde-framework 0.1.2__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fde_framework-0.1.2 → fde_framework-0.1.4}/CHANGELOG.md +43 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/PKG-INFO +55 -16
- {fde_framework-0.1.2 → fde_framework-0.1.4}/README.md +53 -15
- {fde_framework-0.1.2 → fde_framework-0.1.4}/examples/invoice-extraction/README.md +1 -1
- fde_framework-0.1.4/framework/approaches/graph-expanded-retrieval.md +24 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/graph-retrieval.md +6 -3
- fde_framework-0.1.4/framework/approaches/hybrid-search.md +24 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/local-embedding.md +5 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/managed-embedding.md +4 -1
- fde_framework-0.1.4/framework/approaches/reranked-retrieval.md +24 -0
- fde_framework-0.1.4/framework/dimensions/corpus_churn.md +24 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/corpus_size.md +1 -1
- fde_framework-0.1.4/framework/patterns/graph-expanded-retrieval.md +15 -0
- fde_framework-0.1.4/framework/patterns/hybrid-search.md +9 -0
- fde_framework-0.1.4/framework/patterns/reranked-retrieval.md +9 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/vector-search.md +1 -0
- fde_framework-0.1.4/framework/stacks/llamaindex.md +20 -0
- fde_framework-0.1.4/framework/templates/retrieval/graph-expanded-retrieval.pgvector.py.j2 +117 -0
- fde_framework-0.1.4/framework/templates/retrieval/graph-expanded-retrieval.plain.py.j2 +65 -0
- fde_framework-0.1.4/framework/templates/retrieval/graph-expanded-retrieval.qdrant.py.j2 +77 -0
- fde_framework-0.1.4/framework/templates/retrieval/hybrid-search.plain.py.j2 +43 -0
- fde_framework-0.1.4/framework/templates/retrieval/reranked-retrieval.plain.py.j2 +41 -0
- fde_framework-0.1.4/framework/templates/retrieval/vector-search.llamaindex.py.j2 +44 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/pyproject.toml +2 -1
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/cli.py +20 -5
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/costing.py +1 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/emit.py +147 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/ops.py +119 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_coverage.py +29 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_dead_zones.py +30 -0
- fde_framework-0.1.4/tests/test_example_transcript.py +62 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_gates.py +3 -1
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_ops.py +24 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_prose.py +16 -0
- fde_framework-0.1.4/tests/test_retrieval_eval.py +137 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_sanitisation.py +1 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/.gitignore +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/LICENSE +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/ansible-playbook.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/assisted-deterministic.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/audit-only.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/boundary-and-audit.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/cascade.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/classical-ml.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/compose.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/decision-log.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/deterministic-masking.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/deterministic.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/direct-call.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/episodic-store.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/explainability-record.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/field-match.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/finetune.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/fixed-sequence.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/gitops.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/governed-tools.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/judged.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/keyword-search.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/kubernetes-manifests.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/labelled-metrics.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/llm-extraction.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/llm-scrubbing.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/llm.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/managed-api.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/manual-runbook.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/model-planner.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/ocr-pipeline.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/optimisation-reasoning.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/optimisation.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/passthrough.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/role-scoped-authority.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/segmentation.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/self-hosted.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/serverless-gpu.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/speech-transcription.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/structured-logs.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/systemd-unit.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/terraform-module.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/text-extraction.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/traced.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/vector-search.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/video-ingestion.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/windowed-ingestion.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/approaches/working-state.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/cases/churn-scoring.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/cases/route-planning.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/cases/structured-extraction.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/cases/studio-style.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/accountability.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/deployment.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/embedding.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/evaluation.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/governance.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/integration.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/memory.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/observability.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/perception.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/planning.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/provisioning.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/reasoning.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/redaction.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/representation.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/retrieval.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/components/serving.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/accelerator.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/access_model.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/arrival_rate.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/availability_target.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/cheap_path_coverage.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/confidence_calibrated.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/container_competence.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/data_residency.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/environment_lifetime.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/existing_cluster.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/existing_iac_tool.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/external_systems.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/hosting.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/human_waiting.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/input_format.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/interpretability_required.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/labelled_count.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/latency_budget_ms.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/licence_posture.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/operates_after_handover.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/output_shape.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/provisioning_api.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/query_pattern.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/recall_span.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/dimensions/sensitivity_present.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/Generator.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/Guard.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/Mapper.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/ModelServer.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/Parser.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/Planner.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/Retriever.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/Scorer.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/Store.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/ToolBoundary.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/interfaces/Tracer.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/locales/eu-gdpr.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/locales/in-dpdp.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/ansible-playbook.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/assisted-deterministic.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/audit-only.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/boundary-and-audit.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/cascade-reasoning.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/cascade-representation.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/cascade-retrieval.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/classical-ml-reasoning.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/classical-ml.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/compose.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/decision-log.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/deterministic-masking.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/deterministic.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/direct-call.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/episodic-store.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/explainability-record.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/field-match.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/finetune-representation.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/finetune.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/fixed-sequence.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/gitops.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/governed-tools.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/graph-retrieval.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/judged.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/keyword-search.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/kubernetes-manifests.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/labelled-metrics.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/llm-representation.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/llm-scrubbing.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/llm.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/local-embedding.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/managed-api.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/managed-embedding.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/manual-runbook.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/model-planner.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/ocr-pipeline.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/optimisation-reasoning.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/optimisation.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/passthrough.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/role-scoped-authority.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/segmentation.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/self-hosted.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/serverless-gpu.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/speech-transcription.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/structured-logs.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/systemd-unit.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/terraform-module.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/text-extraction.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/traced.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/video-ingestion.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/windowed-ingestion.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/patterns/working-state.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/langgraph.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/local-judge.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/mcp.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/ollama.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/openai-judge.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/opentelemetry.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/ortools.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/pgvector.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/plain-python.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/qdrant.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/tesseract.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/vllm.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/whisper.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/stacks/xgboost.md +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/accountability/decision-log.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/accountability/explainability-record.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/deployment/compose.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/deployment/kubernetes-manifests.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/deployment/systemd-unit.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/embedding/local-embedding.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/embedding/managed-embedding.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/evaluation/field-match.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/evaluation/judged.local-judge.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/evaluation/judged.openai-judge.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/evaluation/judged.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/evaluation/labelled-metrics.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/evaluation/labelled-metrics.xgboost.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/governance/audit-only.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/governance/boundary-and-audit.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/governance/role-scoped-authority.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/integration/direct-call.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/integration/governed-tools.mcp.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/integration/governed-tools.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/memory/episodic-store.pgvector.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/memory/episodic-store.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/memory/working-state.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/observability/structured-logs.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/observability/traced.opentelemetry.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/observability/traced.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/perception/ocr-pipeline.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/perception/ocr-pipeline.tesseract.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/perception/passthrough.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/perception/speech-transcription.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/perception/speech-transcription.whisper.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/perception/text-extraction.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/perception/video-ingestion.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/perception/windowed-ingestion.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/planning/fixed-sequence.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/planning/model-planner.langgraph.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/planning/model-planner.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/planning/optimisation.ortools.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/planning/optimisation.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/provisioning/ansible-playbook.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/provisioning/gitops.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/provisioning/manual-runbook.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/provisioning/terraform-module.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/reasoning/cascade.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/reasoning/classical-ml.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/reasoning/classical-ml.xgboost.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/reasoning/finetune.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/reasoning/llm.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/reasoning/optimisation.ortools.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/reasoning/optimisation.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/redaction/deterministic-masking.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/redaction/llm-scrubbing.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/representation/assisted.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/representation/cascade.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/representation/classical-ml.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/representation/classical-ml.xgboost.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/representation/deterministic.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/representation/finetune.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/representation/llm.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/representation/segmentation.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/retrieval/cascade.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/retrieval/graph-retrieval.pgvector.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/retrieval/graph-retrieval.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/retrieval/graph-retrieval.qdrant.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/retrieval/keyword-search.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/retrieval/vector-search.pgvector.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/retrieval/vector-search.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/retrieval/vector-search.qdrant.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/serving/managed-api.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/serving/self-hosted.ollama.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/serving/self-hosted.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/serving/self-hosted.vllm.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/framework/templates/serving/serverless-gpu.plain.py.j2 +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/__init__.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/architect.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/decide.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/decompose.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/deploy.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/evolution.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/factlog.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/gates.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/graph.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/implement.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/intake/__init__.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/intake/answers.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/intake/documents.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/intake/interview.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/intake/llm_reader.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/intake/prose.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/intake/samples.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/models/__init__.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/models/base.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/models/fact.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/models/profile.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/models/respondent.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/models/schema.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/moves.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/predicate.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/realization.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/registry.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/scan.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/space.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/src/fde/workflow.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/__init__.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/conftest.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/models/__init__.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/models/test_profile.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_access_and_sensitivity.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_answers.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_cascade.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_cli_engagement.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_cli_evolution.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_cli_gates.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_cli_intake.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_cli_kb.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_cli_robustness.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_cli_samples.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_costing.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_decide.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_decompose.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_deploy.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_documents.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_embedding.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_emit.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_evolution.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_factlog.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_implement.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_interview.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_llm_reader.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_locales.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_memory_retrieval.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_more_templates.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_moves.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_multimodal.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_package.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_realization.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_registry.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_remaining.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_reversibility.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_samples.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_scan.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_schema.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_serving.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_shipped_registry.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_space.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_stack_swap.py +0 -0
- {fde_framework-0.1.2 → fde_framework-0.1.4}/tests/test_templates.py +0 -0
|
@@ -5,6 +5,49 @@ the project is pre-release, so everything sits under 0.1.0 until the first tag.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.1.4] — 2026-09-09
|
|
9
|
+
|
|
10
|
+
The measurement release: claims the framework already made, turned into
|
|
11
|
+
numbers and walks.
|
|
12
|
+
|
|
13
|
+
- Projects with a retrieval component ship `evals/retrieval.py`: recall@10
|
|
14
|
+
and recall@50 against golden queries in `retrieval_cases.jsonl`, gated in
|
|
15
|
+
CI, refusing an empty case set. The embedding and index choices set a
|
|
16
|
+
ceiling nothing downstream recovers; this measures the ceiling by itself,
|
|
17
|
+
no model in the loop. The diagnosis walk's evidence step now ends at this
|
|
18
|
+
number, and both embedding approaches record the doctrine: chosen by
|
|
19
|
+
measured recall on the engagement's own queries, never by leaderboard.
|
|
20
|
+
- Emitted projects ship `ops/diagnosis.md`: the walk that finds which layer
|
|
21
|
+
a failure lives in -- definitions, evidence, tools, loop, model -- ordered
|
|
22
|
+
cheapest-to-check first, sections adapted to the components actually in
|
|
23
|
+
the system. An unclear definition can look like a model error; the
|
|
24
|
+
expensive habit is re-prompting before finding out.
|
|
25
|
+
- Retrieval corpus: `corpus_churn` dimension (static/periodic/continuous —
|
|
26
|
+
how fast the document stock turns over, distinct from corpus size and
|
|
27
|
+
query arrival) and a graph-expanded-retrieval approach: vector entry,
|
|
28
|
+
entity expansion, rerank exit, for multi-hop questions on a corpus that
|
|
29
|
+
keeps changing. Full graph-retrieval now steps aside on continuous churn,
|
|
30
|
+
by name, with the reason on the record. Realizations for plain-python,
|
|
31
|
+
pgvector and qdrant.
|
|
32
|
+
- README quickstart shows the gate refusal before the passing build, so the
|
|
33
|
+
first run's refusal is announced rather than a surprise.
|
|
34
|
+
|
|
35
|
+
## [0.1.3] — 2026-09-08
|
|
36
|
+
|
|
37
|
+
A post-launch funnel audit replayed every public transcript against the
|
|
38
|
+
shipped package; everything it caught, in one release:
|
|
39
|
+
|
|
40
|
+
- `fde start` with a statement now also offers the three questions worth
|
|
41
|
+
asking next (the follow-ups hint names the actual engagement path).
|
|
42
|
+
- Seat economics dates its figures; `fde scan` on unified-memory machines
|
|
43
|
+
no longer prints a contradictory "0GB total".
|
|
44
|
+
- Retrieval corpus: hybrid-search and reranked-retrieval (adopted by
|
|
45
|
+
measurement, like finetune); LlamaIndex stack with a realization;
|
|
46
|
+
invoices/complaints/claims join the corpus-size vocabulary.
|
|
47
|
+
- The worked example's transcript is now a replay test: an output change
|
|
48
|
+
that would strand it fails in the same commit.
|
|
49
|
+
- CI tests 3.11/3.12/3.13; doc links absolute so PyPI renders them.
|
|
50
|
+
|
|
8
51
|
## [0.1.2] — 2026-09-07
|
|
9
52
|
|
|
10
53
|
A fresh-eyes usability round, every finding verified in a clean venv:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: fde-framework
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: A framework for Forward Deployed Engineers: from problem statement to a deployable AI project, every decision traced to a fact.
|
|
5
5
|
Project-URL: Homepage, https://github.com/atulkapoor/fde-framework
|
|
6
6
|
Project-URL: Repository, https://github.com/atulkapoor/fde-framework
|
|
@@ -14,6 +14,7 @@ Classifier: Intended Audience :: Developers
|
|
|
14
14
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
18
|
Classifier: Topic :: Software Development :: Code Generators
|
|
18
19
|
Requires-Python: >=3.11
|
|
19
20
|
Requires-Dist: jinja2>=3.1
|
|
@@ -47,15 +48,16 @@ Description-Content-Type: text/markdown
|
|
|
47
48
|

|
|
48
49
|
[](https://pypistats.org/packages/fde-framework)
|
|
49
50
|

|
|
50
|
-
[](LICENSE)
|
|
51
|
+
[](https://github.com/atulkapoor/fde-framework/blob/main/LICENSE)
|
|
51
52
|
|
|
52
53
|
<p>
|
|
53
54
|
<a href="#install">Install</a> ·
|
|
54
|
-
<a href="#try-it
|
|
55
|
+
<a href="#try-it">Quickstart</a> ·
|
|
55
56
|
<a href="ARCHITECTURE.md">Architecture</a> ·
|
|
56
57
|
<a href="examples/invoice-extraction/">Worked example</a> ·
|
|
57
58
|
<a href="CONTRIBUTING.md">Contributing</a> ·
|
|
58
|
-
<a href="https://pypi.org/project/fde-framework/">PyPI</a>
|
|
59
|
+
<a href="https://pypi.org/project/fde-framework/">PyPI</a> ·
|
|
60
|
+
<a href="https://atulkapoor.github.io/fde-framework/">Website</a>
|
|
59
61
|
</p>
|
|
60
62
|
|
|
61
63
|
**fde** is an open-source framework for Forward Deployed Engineers: it takes a
|
|
@@ -74,6 +76,8 @@ pip install fde-framework
|
|
|
74
76
|
fde start acme --statement "Extract fields from supplier invoices."
|
|
75
77
|
fde ask acme --role admin # role-scoped discovery interview
|
|
76
78
|
fde architect acme # the design, with cited rationale
|
|
79
|
+
fde build acme --out project # refuses: seven gates guard the build
|
|
80
|
+
# ...verify data access, capture the baseline (each gate prints its remedy), then:
|
|
77
81
|
fde build acme --out project # code + evals + deploy assets + runbook
|
|
78
82
|
```
|
|
79
83
|
|
|
@@ -94,6 +98,16 @@ access — no build. The remedies ship with every gate.*
|
|
|
94
98
|
| **Jurisdiction as data** | Locale packs preset answers at the weakest provenance and attach dated compliance obligations to the build; they can never change how decisions are made |
|
|
95
99
|
| **Self-evolution, honestly** | Overrides, trigger calibration and anonymised cases are captured per engagement; the corpus grows only through human-reviewed ingestion |
|
|
96
100
|
|
|
101
|
+
|
|
102
|
+
## How it fits together
|
|
103
|
+
|
|
104
|
+
<img src="https://raw.githubusercontent.com/atulkapoor/fde-framework/main/assets/how-it-fits.png" alt="statement to typed facts to answer space to seven gates, then decide, architect, emit, implement — registry as data, deterministic builds" width="800">
|
|
105
|
+
|
|
106
|
+
Discovery narrows an answer space; gates decide whether building is honest
|
|
107
|
+
yet; the decision engine picks the simplest applicable approach per component
|
|
108
|
+
and cites why; emit writes a project whose exam fails until it is truly
|
|
109
|
+
implemented. The full design is in [ARCHITECTURE.md](https://github.com/atulkapoor/fde-framework/blob/main/ARCHITECTURE.md).
|
|
110
|
+
|
|
97
111
|
---
|
|
98
112
|
|
|
99
113
|
## Who this is for
|
|
@@ -261,7 +275,7 @@ check. `--lenient` exists for the hour when you are mid-way through authoring
|
|
|
261
275
|
content and the links do not resolve yet.
|
|
262
276
|
|
|
263
277
|
A complete worked engagement — real transcript, synthetic client — lives in
|
|
264
|
-
[examples/invoice-extraction](examples/invoice-extraction
|
|
278
|
+
[examples/invoice-extraction](https://github.com/atulkapoor/fde-framework/tree/main/examples/invoice-extraction).
|
|
265
279
|
|
|
266
280
|
## What a build emits
|
|
267
281
|
|
|
@@ -270,10 +284,10 @@ project/
|
|
|
270
284
|
├── app/ # components, pipeline, controls, boundary check
|
|
271
285
|
│ ├── components/ # implementations or honest scaffolds — never silent gaps
|
|
272
286
|
│ ├── pipeline.py # topological order; approval gates before anything mutative
|
|
273
|
-
│ ├── controls.py # fail-closed
|
|
287
|
+
│ ├── controls.py # fail-closed gates & critics — when anything mutative was decided
|
|
274
288
|
│ ├── boundary.py # imported at startup when data may not leave
|
|
275
289
|
│ ├── contract.py # RefusedInput: forbidden input is refused, never guessed at
|
|
276
|
-
│ └── llm.py # the one model touchpoint
|
|
290
|
+
│ └── llm.py # the one model touchpoint — when a decision needs a model (boundary-gated)
|
|
277
291
|
├── evals/ # golden / edge / adversarial sets from the client's own pairs
|
|
278
292
|
│ ├── harness.py # fails CI until implemented; judge-based when the evaluation decided judged
|
|
279
293
|
│ ├── acceptance.md # blind UAT protocol for the client's own judges
|
|
@@ -498,7 +512,7 @@ The registry is the shared asset; engagements are private working state.
|
|
|
498
512
|
deliberately waits for a corpus of measured retrospectives rather than
|
|
499
513
|
pretending a handful is evidence.
|
|
500
514
|
- **More locale packs and stacks** — both are data; contributions enter
|
|
501
|
-
against [CONTRIBUTING.md](CONTRIBUTING.md)'s contract (and the [code of conduct](CODE_OF_CONDUCT.md)).
|
|
515
|
+
against [CONTRIBUTING.md](https://github.com/atulkapoor/fde-framework/blob/main/CONTRIBUTING.md)'s contract (and the [code of conduct](https://github.com/atulkapoor/fde-framework/blob/main/CODE_OF_CONDUCT.md)).
|
|
502
516
|
- **Language, channel, and device axes** — six of twenty industry test
|
|
503
517
|
statements named regional languages, low bandwidth, or basic devices;
|
|
504
518
|
the honest wiring (per-language evaluation, SMS/IVR serving approaches,
|
|
@@ -513,22 +527,47 @@ The registry is the shared asset; engagements are private working state.
|
|
|
513
527
|
`fde kb sweep` report what the corpus is missing and which profile shapes
|
|
514
528
|
no approach can serve yet.
|
|
515
529
|
|
|
516
|
-
##
|
|
530
|
+
## Documentation
|
|
531
|
+
|
|
532
|
+
| I want to… | Read |
|
|
533
|
+
|---|---|
|
|
534
|
+
| Run the whole lifecycle once | [The full lifecycle, copy-paste](#the-full-lifecycle-copy-paste) |
|
|
535
|
+
| See a real transcript with expected output | [Worked example](https://github.com/atulkapoor/fde-framework/tree/main/examples/invoice-extraction) |
|
|
536
|
+
| Understand the moving parts | [ARCHITECTURE.md](https://github.com/atulkapoor/fde-framework/blob/main/ARCHITECTURE.md) |
|
|
537
|
+
| Understand a gate that just refused me | `fde status <eng>` — every gate names its remedy and its clearing command |
|
|
538
|
+
| Add a dimension / approach / template | [CONTRIBUTING.md](https://github.com/atulkapoor/fde-framework/blob/main/CONTRIBUTING.md) — incl. the template context table |
|
|
539
|
+
| Use it as a library | [Python API](#python-api) |
|
|
540
|
+
| Report a vulnerability | [SECURITY.md](https://github.com/atulkapoor/fde-framework/blob/main/SECURITY.md) |
|
|
541
|
+
| See what changed | [CHANGELOG.md](https://github.com/atulkapoor/fde-framework/blob/main/CHANGELOG.md) · [Releases](https://github.com/atulkapoor/fde-framework/releases) |
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
## Development
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
git clone https://github.com/atulkapoor/fde-framework.git && cd fde-framework
|
|
548
|
+
python3 -m venv .venv && .venv/bin/pip install -e ".[dev,documents]"
|
|
549
|
+
.venv/bin/pytest -q # ~850 tests, < 30s
|
|
550
|
+
.venv/bin/ruff check src tests
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
The registry is data: most contributions are a markdown file in `framework/`
|
|
554
|
+
plus a test that pins the behaviour. CI additionally runs a sanitisation sweep
|
|
555
|
+
over the tree and history.
|
|
556
|
+
|
|
557
|
+
## Community
|
|
517
558
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
- [SECURITY.md](SECURITY.md) — reporting, and what counts as security-grade here
|
|
522
|
-
- [llms.txt](llms.txt) — the project summarised for AI assistants
|
|
559
|
+
Questions and engagement war stories → [Discussions](https://github.com/atulkapoor/fde-framework/discussions).
|
|
560
|
+
Bugs and corpus gaps → [issues](https://github.com/atulkapoor/fde-framework/issues/new/choose) (the forms ask for evidence, the way the framework does).
|
|
561
|
+
Conduct → [CODE_OF_CONDUCT.md](https://github.com/atulkapoor/fde-framework/blob/main/CODE_OF_CONDUCT.md).
|
|
523
562
|
|
|
524
563
|
## License
|
|
525
564
|
|
|
526
|
-
[Apache 2.0](LICENSE) — chosen for the explicit patent grant, because
|
|
565
|
+
[Apache 2.0](https://github.com/atulkapoor/fde-framework/blob/main/LICENSE) — chosen for the explicit patent grant, because
|
|
527
566
|
enterprise legal review is a real gate for the audience this is for.
|
|
528
567
|
|
|
529
568
|
## Contributing
|
|
530
569
|
|
|
531
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md). The short version: contributions enter
|
|
570
|
+
See [CONTRIBUTING.md](https://github.com/atulkapoor/fde-framework/blob/main/CONTRIBUTING.md). The short version: contributions enter
|
|
532
571
|
against a contract, and **client material never enters this repository** — only
|
|
533
572
|
patterns re-expressed in the framework's own words. Sanitisation is enforced in
|
|
534
573
|
CI: allowed paths only, history checked, credential and personal-data patterns,
|
|
@@ -10,15 +10,16 @@
|
|
|
10
10
|

|
|
11
11
|
[](https://pypistats.org/packages/fde-framework)
|
|
12
12
|

|
|
13
|
-
[](LICENSE)
|
|
13
|
+
[](https://github.com/atulkapoor/fde-framework/blob/main/LICENSE)
|
|
14
14
|
|
|
15
15
|
<p>
|
|
16
16
|
<a href="#install">Install</a> ·
|
|
17
|
-
<a href="#try-it
|
|
17
|
+
<a href="#try-it">Quickstart</a> ·
|
|
18
18
|
<a href="ARCHITECTURE.md">Architecture</a> ·
|
|
19
19
|
<a href="examples/invoice-extraction/">Worked example</a> ·
|
|
20
20
|
<a href="CONTRIBUTING.md">Contributing</a> ·
|
|
21
|
-
<a href="https://pypi.org/project/fde-framework/">PyPI</a>
|
|
21
|
+
<a href="https://pypi.org/project/fde-framework/">PyPI</a> ·
|
|
22
|
+
<a href="https://atulkapoor.github.io/fde-framework/">Website</a>
|
|
22
23
|
</p>
|
|
23
24
|
|
|
24
25
|
**fde** is an open-source framework for Forward Deployed Engineers: it takes a
|
|
@@ -37,6 +38,8 @@ pip install fde-framework
|
|
|
37
38
|
fde start acme --statement "Extract fields from supplier invoices."
|
|
38
39
|
fde ask acme --role admin # role-scoped discovery interview
|
|
39
40
|
fde architect acme # the design, with cited rationale
|
|
41
|
+
fde build acme --out project # refuses: seven gates guard the build
|
|
42
|
+
# ...verify data access, capture the baseline (each gate prints its remedy), then:
|
|
40
43
|
fde build acme --out project # code + evals + deploy assets + runbook
|
|
41
44
|
```
|
|
42
45
|
|
|
@@ -57,6 +60,16 @@ access — no build. The remedies ship with every gate.*
|
|
|
57
60
|
| **Jurisdiction as data** | Locale packs preset answers at the weakest provenance and attach dated compliance obligations to the build; they can never change how decisions are made |
|
|
58
61
|
| **Self-evolution, honestly** | Overrides, trigger calibration and anonymised cases are captured per engagement; the corpus grows only through human-reviewed ingestion |
|
|
59
62
|
|
|
63
|
+
|
|
64
|
+
## How it fits together
|
|
65
|
+
|
|
66
|
+
<img src="https://raw.githubusercontent.com/atulkapoor/fde-framework/main/assets/how-it-fits.png" alt="statement to typed facts to answer space to seven gates, then decide, architect, emit, implement — registry as data, deterministic builds" width="800">
|
|
67
|
+
|
|
68
|
+
Discovery narrows an answer space; gates decide whether building is honest
|
|
69
|
+
yet; the decision engine picks the simplest applicable approach per component
|
|
70
|
+
and cites why; emit writes a project whose exam fails until it is truly
|
|
71
|
+
implemented. The full design is in [ARCHITECTURE.md](https://github.com/atulkapoor/fde-framework/blob/main/ARCHITECTURE.md).
|
|
72
|
+
|
|
60
73
|
---
|
|
61
74
|
|
|
62
75
|
## Who this is for
|
|
@@ -224,7 +237,7 @@ check. `--lenient` exists for the hour when you are mid-way through authoring
|
|
|
224
237
|
content and the links do not resolve yet.
|
|
225
238
|
|
|
226
239
|
A complete worked engagement — real transcript, synthetic client — lives in
|
|
227
|
-
[examples/invoice-extraction](examples/invoice-extraction
|
|
240
|
+
[examples/invoice-extraction](https://github.com/atulkapoor/fde-framework/tree/main/examples/invoice-extraction).
|
|
228
241
|
|
|
229
242
|
## What a build emits
|
|
230
243
|
|
|
@@ -233,10 +246,10 @@ project/
|
|
|
233
246
|
├── app/ # components, pipeline, controls, boundary check
|
|
234
247
|
│ ├── components/ # implementations or honest scaffolds — never silent gaps
|
|
235
248
|
│ ├── pipeline.py # topological order; approval gates before anything mutative
|
|
236
|
-
│ ├── controls.py # fail-closed
|
|
249
|
+
│ ├── controls.py # fail-closed gates & critics — when anything mutative was decided
|
|
237
250
|
│ ├── boundary.py # imported at startup when data may not leave
|
|
238
251
|
│ ├── contract.py # RefusedInput: forbidden input is refused, never guessed at
|
|
239
|
-
│ └── llm.py # the one model touchpoint
|
|
252
|
+
│ └── llm.py # the one model touchpoint — when a decision needs a model (boundary-gated)
|
|
240
253
|
├── evals/ # golden / edge / adversarial sets from the client's own pairs
|
|
241
254
|
│ ├── harness.py # fails CI until implemented; judge-based when the evaluation decided judged
|
|
242
255
|
│ ├── acceptance.md # blind UAT protocol for the client's own judges
|
|
@@ -461,7 +474,7 @@ The registry is the shared asset; engagements are private working state.
|
|
|
461
474
|
deliberately waits for a corpus of measured retrospectives rather than
|
|
462
475
|
pretending a handful is evidence.
|
|
463
476
|
- **More locale packs and stacks** — both are data; contributions enter
|
|
464
|
-
against [CONTRIBUTING.md](CONTRIBUTING.md)'s contract (and the [code of conduct](CODE_OF_CONDUCT.md)).
|
|
477
|
+
against [CONTRIBUTING.md](https://github.com/atulkapoor/fde-framework/blob/main/CONTRIBUTING.md)'s contract (and the [code of conduct](https://github.com/atulkapoor/fde-framework/blob/main/CODE_OF_CONDUCT.md)).
|
|
465
478
|
- **Language, channel, and device axes** — six of twenty industry test
|
|
466
479
|
statements named regional languages, low bandwidth, or basic devices;
|
|
467
480
|
the honest wiring (per-language evaluation, SMS/IVR serving approaches,
|
|
@@ -476,22 +489,47 @@ The registry is the shared asset; engagements are private working state.
|
|
|
476
489
|
`fde kb sweep` report what the corpus is missing and which profile shapes
|
|
477
490
|
no approach can serve yet.
|
|
478
491
|
|
|
479
|
-
##
|
|
492
|
+
## Documentation
|
|
493
|
+
|
|
494
|
+
| I want to… | Read |
|
|
495
|
+
|---|---|
|
|
496
|
+
| Run the whole lifecycle once | [The full lifecycle, copy-paste](#the-full-lifecycle-copy-paste) |
|
|
497
|
+
| See a real transcript with expected output | [Worked example](https://github.com/atulkapoor/fde-framework/tree/main/examples/invoice-extraction) |
|
|
498
|
+
| Understand the moving parts | [ARCHITECTURE.md](https://github.com/atulkapoor/fde-framework/blob/main/ARCHITECTURE.md) |
|
|
499
|
+
| Understand a gate that just refused me | `fde status <eng>` — every gate names its remedy and its clearing command |
|
|
500
|
+
| Add a dimension / approach / template | [CONTRIBUTING.md](https://github.com/atulkapoor/fde-framework/blob/main/CONTRIBUTING.md) — incl. the template context table |
|
|
501
|
+
| Use it as a library | [Python API](#python-api) |
|
|
502
|
+
| Report a vulnerability | [SECURITY.md](https://github.com/atulkapoor/fde-framework/blob/main/SECURITY.md) |
|
|
503
|
+
| See what changed | [CHANGELOG.md](https://github.com/atulkapoor/fde-framework/blob/main/CHANGELOG.md) · [Releases](https://github.com/atulkapoor/fde-framework/releases) |
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
## Development
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
git clone https://github.com/atulkapoor/fde-framework.git && cd fde-framework
|
|
510
|
+
python3 -m venv .venv && .venv/bin/pip install -e ".[dev,documents]"
|
|
511
|
+
.venv/bin/pytest -q # ~850 tests, < 30s
|
|
512
|
+
.venv/bin/ruff check src tests
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
The registry is data: most contributions are a markdown file in `framework/`
|
|
516
|
+
plus a test that pins the behaviour. CI additionally runs a sanitisation sweep
|
|
517
|
+
over the tree and history.
|
|
518
|
+
|
|
519
|
+
## Community
|
|
480
520
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
- [SECURITY.md](SECURITY.md) — reporting, and what counts as security-grade here
|
|
485
|
-
- [llms.txt](llms.txt) — the project summarised for AI assistants
|
|
521
|
+
Questions and engagement war stories → [Discussions](https://github.com/atulkapoor/fde-framework/discussions).
|
|
522
|
+
Bugs and corpus gaps → [issues](https://github.com/atulkapoor/fde-framework/issues/new/choose) (the forms ask for evidence, the way the framework does).
|
|
523
|
+
Conduct → [CODE_OF_CONDUCT.md](https://github.com/atulkapoor/fde-framework/blob/main/CODE_OF_CONDUCT.md).
|
|
486
524
|
|
|
487
525
|
## License
|
|
488
526
|
|
|
489
|
-
[Apache 2.0](LICENSE) — chosen for the explicit patent grant, because
|
|
527
|
+
[Apache 2.0](https://github.com/atulkapoor/fde-framework/blob/main/LICENSE) — chosen for the explicit patent grant, because
|
|
490
528
|
enterprise legal review is a real gate for the audience this is for.
|
|
491
529
|
|
|
492
530
|
## Contributing
|
|
493
531
|
|
|
494
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md). The short version: contributions enter
|
|
532
|
+
See [CONTRIBUTING.md](https://github.com/atulkapoor/fde-framework/blob/main/CONTRIBUTING.md). The short version: contributions enter
|
|
495
533
|
against a contract, and **client material never enters this repository** — only
|
|
496
534
|
patterns re-expressed in the framework's own words. Sanitisation is enforced in
|
|
497
535
|
CI: allowed paths only, history checked, credential and personal-data patterns,
|
|
@@ -25,7 +25,7 @@ fde frame engagements/acme --file examples/invoice-extraction/brief.md
|
|
|
25
25
|
#
|
|
26
26
|
# Correct anything wrong before we go further.
|
|
27
27
|
#
|
|
28
|
-
# worth asking next (fde ask
|
|
28
|
+
# worth asking next (fde ask engagements/acme --role <who>):
|
|
29
29
|
# - What accelerator does the machine this runs on have? [admin]
|
|
30
30
|
# - Who may use this -- one operating team, distinct roles with different
|
|
31
31
|
# permissions, or anyone internal? [admin/sponsor]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: graph-expanded-retrieval
|
|
3
|
+
name: Graph-expanded retrieval
|
|
4
|
+
complexity: 3
|
|
5
|
+
components: [retrieval]
|
|
6
|
+
applies_when: [query_pattern == multi_hop and corpus_churn == continuous]
|
|
7
|
+
avoid_when: [query_pattern == lookup]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: low, last_verified: 2026-09-09}
|
|
9
|
+
---
|
|
10
|
+
Vector search finds the entry points, the entities they mention open the
|
|
11
|
+
graph, a bounded expansion collects what connects, and a reranker orders the
|
|
12
|
+
merged pool. Most of what a full graph buys on multi-hop questions -- without
|
|
13
|
+
asking the graph to carry recall.
|
|
14
|
+
|
|
15
|
+
That one reassignment is what survives churn. With vector search carrying
|
|
16
|
+
recall, the graph keeps a lighter contract -- entities and first-class edges,
|
|
17
|
+
rebuilt incrementally -- instead of the exhaustive index whose super-linear
|
|
18
|
+
growth and drifting entity resolution turn a moving corpus's graph
|
|
19
|
+
confidently wrong.
|
|
20
|
+
|
|
21
|
+
Where the corpus holds still, the full graph still wins: richer edges, deeper
|
|
22
|
+
traversal, no rerank pass to pay for. This exists for the corpus that will
|
|
23
|
+
not hold still. And like the reranker, it is adopted on measurement rather
|
|
24
|
+
than fashion: run the golden multi-hop queries and let the recall gap argue.
|
|
@@ -4,8 +4,8 @@ name: Graph retrieval
|
|
|
4
4
|
complexity: 3
|
|
5
5
|
components: [retrieval]
|
|
6
6
|
applies_when: [query_pattern == multi_hop]
|
|
7
|
-
avoid_when: [query_pattern == lookup, query_pattern == comparative]
|
|
8
|
-
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-
|
|
7
|
+
avoid_when: [query_pattern == lookup, query_pattern == comparative, corpus_churn == continuous]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-09-09}
|
|
9
9
|
---
|
|
10
10
|
Explicit entities and edges, traversed at query time.
|
|
11
11
|
|
|
@@ -16,7 +16,10 @@ rather than an upgrade.
|
|
|
16
16
|
|
|
17
17
|
The costs are real: multi-pass extraction to build it, two to three times the
|
|
18
18
|
end-to-end latency to use it, and an index that grows super-linearly, which is
|
|
19
|
-
what makes incremental updates painful on a corpus that changes.
|
|
19
|
+
what makes incremental updates painful on a corpus that changes. Where the
|
|
20
|
+
corpus changes continuously, that maintenance is the deciding cost --
|
|
21
|
+
graph-expanded retrieval keeps the multi-hop benefit by letting vector search
|
|
22
|
+
carry recall, so the graph can stay small enough to rebuild.
|
|
20
23
|
|
|
21
24
|
Published gains also warrant scepticism -- judge position bias has been shown to
|
|
22
25
|
swing reported win rates by tens of points. Measure on your own traffic.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: hybrid-search
|
|
3
|
+
name: Hybrid search
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [retrieval]
|
|
6
|
+
applies_when: [query_pattern == comparative and corpus_size > 100000]
|
|
7
|
+
avoid_when: [query_pattern == multi_hop, corpus_size < 10000]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-09-07}
|
|
9
|
+
---
|
|
10
|
+
Keyword and semantic retrieval fused, because each fails where the other
|
|
11
|
+
holds: exact identifiers, part numbers and names that embeddings blur past
|
|
12
|
+
are what BM25 was built for, and paraphrase is what it cannot see. Fusion
|
|
13
|
+
(reciprocal rank, not score mixing -- scores from different retrievers do
|
|
14
|
+
not share a scale) takes both.
|
|
15
|
+
|
|
16
|
+
Earns its second index where the corpus is large enough that either
|
|
17
|
+
retriever alone leaves recall on the table, and comparative queries mix
|
|
18
|
+
named things with described things. Below ten thousand documents, one good
|
|
19
|
+
retriever plus a rerank is less to operate than two indexes that must stay
|
|
20
|
+
in sync -- the sync is the real cost, and it fails silently.
|
|
21
|
+
|
|
22
|
+
Reached by override wherever the sample queries show identifier-plus-prose
|
|
23
|
+
mixtures the chosen retriever measurably misses; the golden set is the
|
|
24
|
+
evidence, never the hunch.
|
|
@@ -19,6 +19,11 @@ Ruled out where nobody is named to operate it. A model with no owner is a
|
|
|
19
19
|
liability handed over with a bow on it, and an embedding model whose host dies
|
|
20
20
|
takes the index with it.
|
|
21
21
|
|
|
22
|
+
Whichever model, it sets the ceiling on retrieval: nothing downstream
|
|
23
|
+
recovers a document that was never encoded well enough to surface. The
|
|
24
|
+
choice is made by measured recall on the engagement's own golden queries --
|
|
25
|
+
the emitted `evals/retrieval.py` is that measurement -- not by leaderboard.
|
|
26
|
+
|
|
22
27
|
The handover concern is stated precisely rather than broadly: with nobody
|
|
23
28
|
named to operate and data free to leave, the managed alternative is
|
|
24
29
|
strictly simpler and wins. But where data cannot leave, the plain
|
|
@@ -19,4 +19,7 @@ to their source, so this is not a way of anonymising anything on the way out.
|
|
|
19
19
|
|
|
20
20
|
One-way, like any vendor call. And expensive to reverse for a second reason --
|
|
21
21
|
changing embedding model means reindexing everything, so leaving is a
|
|
22
|
-
reindexing project rather than a configuration change.
|
|
22
|
+
reindexing project rather than a configuration change. Which is exactly why
|
|
23
|
+
the model is chosen by measured recall on the engagement's own golden
|
|
24
|
+
queries (the emitted `evals/retrieval.py`) rather than by leaderboard: the
|
|
25
|
+
reindexing bill for a wrong guess arrives after the index is full.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: reranked-retrieval
|
|
3
|
+
name: Reranked retrieval
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [retrieval]
|
|
6
|
+
applies_when: [query_pattern == lookup and corpus_size > 200000 and human_waiting == "no"]
|
|
7
|
+
avoid_when: [latency_budget_ms < 500, query_pattern == multi_hop]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-09-07}
|
|
9
|
+
---
|
|
10
|
+
A cheap retriever casts wide, a cross-encoder reads the top candidates
|
|
11
|
+
properly, and precision comes from the second pass. The first-stage
|
|
12
|
+
retriever's job quietly changes from "rank correctly" to "do not miss" --
|
|
13
|
+
recall at fifty, not precision at five -- which is a much easier contract to
|
|
14
|
+
keep on a big corpus.
|
|
15
|
+
|
|
16
|
+
The cost is a model call per query on the reranking pass, which is why the
|
|
17
|
+
latency budget avoids it where somebody is waiting on a tight budget: a
|
|
18
|
+
cross-encoder over fifty candidates is real milliseconds, and no fusion
|
|
19
|
+
trick refunds them.
|
|
20
|
+
|
|
21
|
+
Like the finetune rule, this is mostly reached by measurement rather than by
|
|
22
|
+
default: run the golden queries, look at where the right answer ranked, and
|
|
23
|
+
adopt the reranker when the gap between position one and position twenty is
|
|
24
|
+
where your answers actually live.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: corpus_churn
|
|
3
|
+
type: enum
|
|
4
|
+
scope: data
|
|
5
|
+
kind: requirement
|
|
6
|
+
weight: 1.0
|
|
7
|
+
asks: "How often does the document corpus itself change?"
|
|
8
|
+
ask_role: [admin, user]
|
|
9
|
+
values: [static, periodic, continuous]
|
|
10
|
+
recognises:
|
|
11
|
+
static: [historical archive, frozen corpus, fixed set of documents, one-time snapshot, corpus is static, closed cases]
|
|
12
|
+
periodic: [refreshed monthly, monthly refresh, refreshed weekly, quarterly refresh, batch refresh, re-indexed every]
|
|
13
|
+
continuous: [updated continuously, constantly changing, changes daily, keeps changing, new documents arrive daily, updated throughout the day, live document feed]
|
|
14
|
+
---
|
|
15
|
+
`corpus_size` is stock and `arrival_rate` is the flow of questions; this is
|
|
16
|
+
how fast the stock itself turns over. Nobody volunteers it, because no demo
|
|
17
|
+
runs long enough to feel it.
|
|
18
|
+
|
|
19
|
+
Any index that is expensive to rebuild pays this rate forever, and the
|
|
20
|
+
expensive ones fail politely: retrieval keeps answering, fluently, from a
|
|
21
|
+
corpus that is no longer the client's. An entity graph pays the rate worst --
|
|
22
|
+
extraction is multi-pass, the index grows super-linearly, and entity
|
|
23
|
+
resolution drifts as names and structures change, which is how a graph goes
|
|
24
|
+
from wrong to confidently wrong without an error in any log.
|
|
@@ -6,7 +6,7 @@ kind: requirement
|
|
|
6
6
|
weight: 1.5
|
|
7
7
|
asks: "How many items in total?"
|
|
8
8
|
recognises_near:
|
|
9
|
-
[documents, docs, document, files, records, pages, rows, accounts, items, tickets, reports, corpus]
|
|
9
|
+
[documents, docs, document, files, records, pages, rows, accounts, items, tickets, reports, corpus, invoices, complaints, claims]
|
|
10
10
|
ask_role: ['admin', 'eval_owner']
|
|
11
11
|
---
|
|
12
12
|
Total volume. Distinct from how many are labelled, which is usually far smaller
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: graph-expanded-retrieval
|
|
3
|
+
component: retrieval
|
|
4
|
+
approach: graph-expanded-retrieval
|
|
5
|
+
realizations:
|
|
6
|
+
- {stack: plain-python, template: retrieval/graph-expanded-retrieval.plain.py.j2, provides: Retriever}
|
|
7
|
+
- {stack: pgvector, template: retrieval/graph-expanded-retrieval.pgvector.py.j2, provides: Retriever}
|
|
8
|
+
- {stack: qdrant, template: retrieval/graph-expanded-retrieval.qdrant.py.j2, provides: Retriever}
|
|
9
|
+
evidence: {case_ids: [structured-extraction], confidence: low, last_verified: 2026-09-09}
|
|
10
|
+
---
|
|
11
|
+
Implements graph-expanded-retrieval for retrieval, satisfying Retriever.
|
|
12
|
+
|
|
13
|
+
Vector entry, entity expansion, rerank exit. The graph is deliberately the
|
|
14
|
+
junior partner: it contributes connections, never recall, which is what lets
|
|
15
|
+
it stay small enough to rebuild as the corpus moves.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: hybrid-search
|
|
3
|
+
component: retrieval
|
|
4
|
+
approach: hybrid-search
|
|
5
|
+
realizations:
|
|
6
|
+
- {stack: plain-python, template: retrieval/hybrid-search.plain.py.j2, provides: Retriever}
|
|
7
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-09-07}
|
|
8
|
+
---
|
|
9
|
+
Implements hybrid-search for retrieval, satisfying Retriever.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: reranked-retrieval
|
|
3
|
+
component: retrieval
|
|
4
|
+
approach: reranked-retrieval
|
|
5
|
+
realizations:
|
|
6
|
+
- {stack: plain-python, template: retrieval/reranked-retrieval.plain.py.j2, provides: Retriever}
|
|
7
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-09-07}
|
|
8
|
+
---
|
|
9
|
+
Implements reranked-retrieval for retrieval, satisfying Retriever.
|
|
@@ -6,6 +6,7 @@ realizations:
|
|
|
6
6
|
- {stack: plain-python, template: retrieval/vector-search.plain.py.j2, provides: Retriever}
|
|
7
7
|
- {stack: pgvector, template: retrieval/vector-search.pgvector.py.j2, provides: Retriever}
|
|
8
8
|
- {stack: qdrant, template: retrieval/vector-search.qdrant.py.j2, provides: Retriever}
|
|
9
|
+
- {stack: llamaindex, template: retrieval/vector-search.llamaindex.py.j2, provides: Retriever}
|
|
9
10
|
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-08-21}
|
|
10
11
|
---
|
|
11
12
|
Implements vector-search for retrieval, satisfying Retriever.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: llamaindex
|
|
3
|
+
name: LlamaIndex
|
|
4
|
+
licence: MIT
|
|
5
|
+
topologies: [public-saas, managed-api, customer-vpc, hybrid, on-prem]
|
|
6
|
+
last_verified: 2026-09-07
|
|
7
|
+
provides: {Retriever: stable}
|
|
8
|
+
reversibility: moderate
|
|
9
|
+
---
|
|
10
|
+
The data layer of the LLM framework stack: ingestion, indexing, query
|
|
11
|
+
engines, RAG plumbing. Earns its place where the client already runs it or
|
|
12
|
+
where the retrieval surface is complex enough (many sources, many readers)
|
|
13
|
+
that its connectors beat hand-rolled ingestion -- the published clinical-QA
|
|
14
|
+
deployments are built exactly this way.
|
|
15
|
+
|
|
16
|
+
Moderate reversibility on purpose: its index formats and query-engine
|
|
17
|
+
abstractions weave into the retrieval path, and unwinding them is a
|
|
18
|
+
re-embedding project, not a refactor. Where nothing justifies carrying the
|
|
19
|
+
framework, the plain-python and pgvector realizations answer the same
|
|
20
|
+
contract with less to own.
|