fde-framework 0.1.0__py3-none-any.whl
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/__init__.py +3 -0
- fde/architect.py +152 -0
- fde/cli.py +2107 -0
- fde/costing.py +292 -0
- fde/decide.py +297 -0
- fde/decompose.py +54 -0
- fde/deploy.py +371 -0
- fde/emit.py +1309 -0
- fde/evolution.py +265 -0
- fde/factlog.py +369 -0
- fde/framework/approaches/ansible-playbook.md +22 -0
- fde/framework/approaches/assisted-deterministic.md +37 -0
- fde/framework/approaches/audit-only.md +23 -0
- fde/framework/approaches/boundary-and-audit.md +18 -0
- fde/framework/approaches/cascade.md +32 -0
- fde/framework/approaches/classical-ml.md +21 -0
- fde/framework/approaches/compose.md +18 -0
- fde/framework/approaches/decision-log.md +21 -0
- fde/framework/approaches/deterministic-masking.md +18 -0
- fde/framework/approaches/deterministic.md +25 -0
- fde/framework/approaches/direct-call.md +10 -0
- fde/framework/approaches/episodic-store.md +17 -0
- fde/framework/approaches/explainability-record.md +14 -0
- fde/framework/approaches/field-match.md +15 -0
- fde/framework/approaches/finetune.md +29 -0
- fde/framework/approaches/fixed-sequence.md +19 -0
- fde/framework/approaches/gitops.md +18 -0
- fde/framework/approaches/governed-tools.md +18 -0
- fde/framework/approaches/graph-retrieval.md +22 -0
- fde/framework/approaches/judged.md +15 -0
- fde/framework/approaches/keyword-search.md +11 -0
- fde/framework/approaches/kubernetes-manifests.md +19 -0
- fde/framework/approaches/labelled-metrics.md +14 -0
- fde/framework/approaches/llm-extraction.md +26 -0
- fde/framework/approaches/llm-scrubbing.md +20 -0
- fde/framework/approaches/llm.md +23 -0
- fde/framework/approaches/local-embedding.md +28 -0
- fde/framework/approaches/managed-api.md +49 -0
- fde/framework/approaches/managed-embedding.md +22 -0
- fde/framework/approaches/manual-runbook.md +32 -0
- fde/framework/approaches/model-planner.md +19 -0
- fde/framework/approaches/ocr-pipeline.md +13 -0
- fde/framework/approaches/optimisation-reasoning.md +30 -0
- fde/framework/approaches/optimisation.md +19 -0
- fde/framework/approaches/passthrough.md +11 -0
- fde/framework/approaches/role-scoped-authority.md +19 -0
- fde/framework/approaches/segmentation.md +29 -0
- fde/framework/approaches/self-hosted.md +38 -0
- fde/framework/approaches/serverless-gpu.md +27 -0
- fde/framework/approaches/speech-transcription.md +21 -0
- fde/framework/approaches/structured-logs.md +11 -0
- fde/framework/approaches/systemd-unit.md +30 -0
- fde/framework/approaches/terraform-module.md +22 -0
- fde/framework/approaches/text-extraction.md +14 -0
- fde/framework/approaches/traced.md +24 -0
- fde/framework/approaches/vector-search.md +17 -0
- fde/framework/approaches/video-ingestion.md +16 -0
- fde/framework/approaches/windowed-ingestion.md +25 -0
- fde/framework/approaches/working-state.md +13 -0
- fde/framework/cases/churn-scoring.md +45 -0
- fde/framework/cases/route-planning.md +44 -0
- fde/framework/cases/structured-extraction.md +48 -0
- fde/framework/cases/studio-style.md +46 -0
- fde/framework/components/accountability.md +20 -0
- fde/framework/components/deployment.md +19 -0
- fde/framework/components/embedding.md +23 -0
- fde/framework/components/evaluation.md +13 -0
- fde/framework/components/governance.md +19 -0
- fde/framework/components/integration.md +13 -0
- fde/framework/components/memory.md +21 -0
- fde/framework/components/observability.md +13 -0
- fde/framework/components/perception.md +15 -0
- fde/framework/components/planning.md +15 -0
- fde/framework/components/provisioning.md +17 -0
- fde/framework/components/reasoning.md +20 -0
- fde/framework/components/redaction.md +18 -0
- fde/framework/components/representation.md +13 -0
- fde/framework/components/retrieval.md +13 -0
- fde/framework/components/serving.md +20 -0
- fde/framework/dimensions/accelerator.md +29 -0
- fde/framework/dimensions/access_model.md +25 -0
- fde/framework/dimensions/arrival_rate.md +19 -0
- fde/framework/dimensions/availability_target.md +23 -0
- fde/framework/dimensions/cheap_path_coverage.md +21 -0
- fde/framework/dimensions/confidence_calibrated.md +30 -0
- fde/framework/dimensions/container_competence.md +22 -0
- fde/framework/dimensions/corpus_size.md +13 -0
- fde/framework/dimensions/data_residency.md +36 -0
- fde/framework/dimensions/environment_lifetime.md +19 -0
- fde/framework/dimensions/existing_cluster.md +22 -0
- fde/framework/dimensions/existing_iac_tool.md +25 -0
- fde/framework/dimensions/external_systems.md +15 -0
- fde/framework/dimensions/hosting.md +45 -0
- fde/framework/dimensions/human_waiting.md +41 -0
- fde/framework/dimensions/input_format.md +29 -0
- fde/framework/dimensions/interpretability_required.md +24 -0
- fde/framework/dimensions/labelled_count.md +15 -0
- fde/framework/dimensions/latency_budget_ms.md +16 -0
- fde/framework/dimensions/licence_posture.md +28 -0
- fde/framework/dimensions/operates_after_handover.md +25 -0
- fde/framework/dimensions/output_shape.md +29 -0
- fde/framework/dimensions/provisioning_api.md +18 -0
- fde/framework/dimensions/query_pattern.md +25 -0
- fde/framework/dimensions/recall_span.md +22 -0
- fde/framework/dimensions/sensitivity_present.md +22 -0
- fde/framework/interfaces/Generator.md +5 -0
- fde/framework/interfaces/Guard.md +5 -0
- fde/framework/interfaces/Mapper.md +5 -0
- fde/framework/interfaces/ModelServer.md +5 -0
- fde/framework/interfaces/Parser.md +5 -0
- fde/framework/interfaces/Planner.md +5 -0
- fde/framework/interfaces/Retriever.md +5 -0
- fde/framework/interfaces/Scorer.md +5 -0
- fde/framework/interfaces/Store.md +5 -0
- fde/framework/interfaces/ToolBoundary.md +5 -0
- fde/framework/interfaces/Tracer.md +5 -0
- fde/framework/locales/eu-gdpr.md +51 -0
- fde/framework/locales/in-dpdp.md +46 -0
- fde/framework/patterns/ansible-playbook.md +9 -0
- fde/framework/patterns/assisted-deterministic.md +11 -0
- fde/framework/patterns/audit-only.md +9 -0
- fde/framework/patterns/boundary-and-audit.md +12 -0
- fde/framework/patterns/cascade-reasoning.md +10 -0
- fde/framework/patterns/cascade-representation.md +10 -0
- fde/framework/patterns/cascade-retrieval.md +10 -0
- fde/framework/patterns/classical-ml-reasoning.md +15 -0
- fde/framework/patterns/classical-ml.md +13 -0
- fde/framework/patterns/compose.md +9 -0
- fde/framework/patterns/decision-log.md +9 -0
- fde/framework/patterns/deterministic-masking.md +9 -0
- fde/framework/patterns/deterministic.md +12 -0
- fde/framework/patterns/direct-call.md +12 -0
- fde/framework/patterns/episodic-store.md +13 -0
- fde/framework/patterns/explainability-record.md +9 -0
- fde/framework/patterns/field-match.md +12 -0
- fde/framework/patterns/finetune-representation.md +14 -0
- fde/framework/patterns/finetune.md +12 -0
- fde/framework/patterns/fixed-sequence.md +12 -0
- fde/framework/patterns/gitops.md +9 -0
- fde/framework/patterns/governed-tools.md +13 -0
- fde/framework/patterns/graph-retrieval.md +14 -0
- fde/framework/patterns/judged.md +14 -0
- fde/framework/patterns/keyword-search.md +12 -0
- fde/framework/patterns/kubernetes-manifests.md +9 -0
- fde/framework/patterns/labelled-metrics.md +13 -0
- fde/framework/patterns/llm-representation.md +17 -0
- fde/framework/patterns/llm-scrubbing.md +9 -0
- fde/framework/patterns/llm.md +12 -0
- fde/framework/patterns/local-embedding.md +9 -0
- fde/framework/patterns/managed-api.md +12 -0
- fde/framework/patterns/managed-embedding.md +9 -0
- fde/framework/patterns/manual-runbook.md +9 -0
- fde/framework/patterns/model-planner.md +13 -0
- fde/framework/patterns/ocr-pipeline.md +13 -0
- fde/framework/patterns/optimisation-reasoning.md +15 -0
- fde/framework/patterns/optimisation.md +13 -0
- fde/framework/patterns/passthrough.md +12 -0
- fde/framework/patterns/role-scoped-authority.md +9 -0
- fde/framework/patterns/segmentation.md +12 -0
- fde/framework/patterns/self-hosted.md +14 -0
- fde/framework/patterns/serverless-gpu.md +12 -0
- fde/framework/patterns/speech-transcription.md +10 -0
- fde/framework/patterns/structured-logs.md +12 -0
- fde/framework/patterns/systemd-unit.md +9 -0
- fde/framework/patterns/terraform-module.md +9 -0
- fde/framework/patterns/text-extraction.md +12 -0
- fde/framework/patterns/traced.md +13 -0
- fde/framework/patterns/vector-search.md +14 -0
- fde/framework/patterns/video-ingestion.md +9 -0
- fde/framework/patterns/windowed-ingestion.md +12 -0
- fde/framework/patterns/working-state.md +12 -0
- fde/framework/stacks/langgraph.md +9 -0
- fde/framework/stacks/local-judge.md +9 -0
- fde/framework/stacks/mcp.md +9 -0
- fde/framework/stacks/ollama.md +19 -0
- fde/framework/stacks/openai-judge.md +9 -0
- fde/framework/stacks/opentelemetry.md +9 -0
- fde/framework/stacks/ortools.md +9 -0
- fde/framework/stacks/pgvector.md +9 -0
- fde/framework/stacks/plain-python.md +9 -0
- fde/framework/stacks/qdrant.md +9 -0
- fde/framework/stacks/tesseract.md +9 -0
- fde/framework/stacks/vllm.md +9 -0
- fde/framework/stacks/whisper.md +15 -0
- fde/framework/stacks/xgboost.md +9 -0
- fde/framework/templates/accountability/decision-log.plain.py.j2 +64 -0
- fde/framework/templates/accountability/explainability-record.plain.py.j2 +90 -0
- fde/framework/templates/deployment/compose.plain.py.j2 +36 -0
- fde/framework/templates/deployment/kubernetes-manifests.plain.py.j2 +36 -0
- fde/framework/templates/deployment/systemd-unit.plain.py.j2 +36 -0
- fde/framework/templates/embedding/local-embedding.plain.py.j2 +71 -0
- fde/framework/templates/embedding/managed-embedding.plain.py.j2 +76 -0
- fde/framework/templates/evaluation/field-match.plain.py.j2 +146 -0
- fde/framework/templates/evaluation/judged.local-judge.py.j2 +100 -0
- fde/framework/templates/evaluation/judged.openai-judge.py.j2 +70 -0
- fde/framework/templates/evaluation/judged.plain.py.j2 +89 -0
- fde/framework/templates/evaluation/labelled-metrics.plain.py.j2 +64 -0
- fde/framework/templates/evaluation/labelled-metrics.xgboost.py.j2 +72 -0
- fde/framework/templates/governance/audit-only.plain.py.j2 +98 -0
- fde/framework/templates/governance/boundary-and-audit.plain.py.j2 +142 -0
- fde/framework/templates/governance/role-scoped-authority.plain.py.j2 +63 -0
- fde/framework/templates/integration/direct-call.plain.py.j2 +63 -0
- fde/framework/templates/integration/governed-tools.mcp.py.j2 +124 -0
- fde/framework/templates/integration/governed-tools.plain.py.j2 +153 -0
- fde/framework/templates/memory/episodic-store.pgvector.py.j2 +118 -0
- fde/framework/templates/memory/episodic-store.plain.py.j2 +147 -0
- fde/framework/templates/memory/working-state.plain.py.j2 +48 -0
- fde/framework/templates/observability/structured-logs.plain.py.j2 +61 -0
- fde/framework/templates/observability/traced.opentelemetry.py.j2 +65 -0
- fde/framework/templates/observability/traced.plain.py.j2 +132 -0
- fde/framework/templates/perception/ocr-pipeline.plain.py.j2 +71 -0
- fde/framework/templates/perception/ocr-pipeline.tesseract.py.j2 +80 -0
- fde/framework/templates/perception/passthrough.plain.py.j2 +41 -0
- fde/framework/templates/perception/speech-transcription.plain.py.j2 +37 -0
- fde/framework/templates/perception/speech-transcription.whisper.py.j2 +39 -0
- fde/framework/templates/perception/text-extraction.plain.py.j2 +88 -0
- fde/framework/templates/perception/video-ingestion.plain.py.j2 +35 -0
- fde/framework/templates/perception/windowed-ingestion.plain.py.j2 +69 -0
- fde/framework/templates/planning/fixed-sequence.plain.py.j2 +46 -0
- fde/framework/templates/planning/model-planner.langgraph.py.j2 +89 -0
- fde/framework/templates/planning/model-planner.plain.py.j2 +82 -0
- fde/framework/templates/planning/optimisation.ortools.py.j2 +90 -0
- fde/framework/templates/planning/optimisation.plain.py.j2 +71 -0
- fde/framework/templates/provisioning/ansible-playbook.plain.py.j2 +29 -0
- fde/framework/templates/provisioning/gitops.plain.py.j2 +29 -0
- fde/framework/templates/provisioning/manual-runbook.plain.py.j2 +29 -0
- fde/framework/templates/provisioning/terraform-module.plain.py.j2 +29 -0
- fde/framework/templates/reasoning/cascade.plain.py.j2 +86 -0
- fde/framework/templates/reasoning/classical-ml.plain.py.j2 +74 -0
- fde/framework/templates/reasoning/classical-ml.xgboost.py.j2 +104 -0
- fde/framework/templates/reasoning/finetune.plain.py.j2 +73 -0
- fde/framework/templates/reasoning/llm.plain.py.j2 +114 -0
- fde/framework/templates/reasoning/optimisation.ortools.py.j2 +90 -0
- fde/framework/templates/reasoning/optimisation.plain.py.j2 +58 -0
- fde/framework/templates/redaction/deterministic-masking.plain.py.j2 +44 -0
- fde/framework/templates/redaction/llm-scrubbing.plain.py.j2 +40 -0
- fde/framework/templates/representation/assisted.plain.py.j2 +86 -0
- fde/framework/templates/representation/cascade.plain.py.j2 +119 -0
- fde/framework/templates/representation/classical-ml.plain.py.j2 +74 -0
- fde/framework/templates/representation/classical-ml.xgboost.py.j2 +104 -0
- fde/framework/templates/representation/deterministic.plain.py.j2 +101 -0
- fde/framework/templates/representation/finetune.plain.py.j2 +68 -0
- fde/framework/templates/representation/llm.plain.py.j2 +94 -0
- fde/framework/templates/representation/segmentation.plain.py.j2 +68 -0
- fde/framework/templates/retrieval/cascade.plain.py.j2 +86 -0
- fde/framework/templates/retrieval/graph-retrieval.pgvector.py.j2 +88 -0
- fde/framework/templates/retrieval/graph-retrieval.plain.py.j2 +74 -0
- fde/framework/templates/retrieval/graph-retrieval.qdrant.py.j2 +71 -0
- fde/framework/templates/retrieval/keyword-search.plain.py.j2 +104 -0
- fde/framework/templates/retrieval/vector-search.pgvector.py.j2 +100 -0
- fde/framework/templates/retrieval/vector-search.plain.py.j2 +84 -0
- fde/framework/templates/retrieval/vector-search.qdrant.py.j2 +60 -0
- fde/framework/templates/serving/managed-api.plain.py.j2 +74 -0
- fde/framework/templates/serving/self-hosted.ollama.py.j2 +47 -0
- fde/framework/templates/serving/self-hosted.plain.py.j2 +117 -0
- fde/framework/templates/serving/self-hosted.vllm.py.j2 +77 -0
- fde/framework/templates/serving/serverless-gpu.plain.py.j2 +62 -0
- fde/gates.py +480 -0
- fde/graph.py +435 -0
- fde/implement.py +250 -0
- fde/intake/__init__.py +0 -0
- fde/intake/answers.py +154 -0
- fde/intake/documents.py +121 -0
- fde/intake/interview.py +218 -0
- fde/intake/llm_reader.py +336 -0
- fde/intake/prose.py +387 -0
- fde/intake/samples.py +369 -0
- fde/models/__init__.py +0 -0
- fde/models/base.py +86 -0
- fde/models/fact.py +37 -0
- fde/models/profile.py +159 -0
- fde/models/respondent.py +34 -0
- fde/models/schema.py +430 -0
- fde/moves.py +136 -0
- fde/ops.py +349 -0
- fde/predicate.py +106 -0
- fde/realization.py +109 -0
- fde/registry.py +162 -0
- fde/scan.py +479 -0
- fde/space.py +172 -0
- fde/workflow.py +233 -0
- fde_framework-0.1.0.dist-info/METADATA +449 -0
- fde_framework-0.1.0.dist-info/RECORD +286 -0
- fde_framework-0.1.0.dist-info/WHEEL +4 -0
- fde_framework-0.1.0.dist-info/entry_points.txt +2 -0
- fde_framework-0.1.0.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: audit-only
|
|
3
|
+
name: Audit trail
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [governance]
|
|
6
|
+
applies_when: [data_residency == may_leave]
|
|
7
|
+
avoid_when: [access_model == role_based, data_residency == cannot_leave, hosting == air-gapped]
|
|
8
|
+
evidence: {case_ids: [churn-scoring], confidence: high, last_verified: 2026-08-25}
|
|
9
|
+
---
|
|
10
|
+
A record of what happened, without a boundary around where it happened.
|
|
11
|
+
|
|
12
|
+
The right answer where nothing forbids egress but actions are still taken on
|
|
13
|
+
someone's behalf. Enforcing placement costs real complexity -- split
|
|
14
|
+
deployments, pinned components, a build that fails on a topology change -- and
|
|
15
|
+
paying for it when nothing requires it is the over-engineering the residency
|
|
16
|
+
question exists to prevent.
|
|
17
|
+
|
|
18
|
+
Residency and isolation are not the same requirement, and conflating them is a
|
|
19
|
+
known and expensive mistake. Data staying in a region satisfies one; only
|
|
20
|
+
staying inside a boundary satisfies the other.
|
|
21
|
+
|
|
22
|
+
What does not change: the record names the human as subject and the agent as
|
|
23
|
+
actor, and the trail never fails open into silence.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: boundary-and-audit
|
|
3
|
+
name: Boundary and audit
|
|
4
|
+
complexity: 1
|
|
5
|
+
components: [governance]
|
|
6
|
+
applies_when: [data_residency == cannot_leave, hosting == air-gapped]
|
|
7
|
+
avoid_when: [access_model == role_based, data_residency == may_leave]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: high, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
Not needed where nothing forbids egress -- a boundary around data free to
|
|
11
|
+
move is ceremony. Placement enforced structurally, and an append-only record of what happened.
|
|
12
|
+
|
|
13
|
+
Entitlements are inherited, never granted: what an agent may do is the
|
|
14
|
+
intersection of what the delegating person may do, what it is scoped to, and
|
|
15
|
+
what the tool requires. Never a union.
|
|
16
|
+
|
|
17
|
+
The audit names the human as subject and the agent as actor. A record saying an
|
|
18
|
+
agent issued a refund has lost the accountability chain.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: cascade
|
|
3
|
+
name: Cascade
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [representation, retrieval, reasoning]
|
|
6
|
+
applies_when: [confidence_calibrated == true and cheap_path_coverage < 0.95]
|
|
7
|
+
avoid_when: [confidence_calibrated == false, interpretability_required == true]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-08-24}
|
|
9
|
+
---
|
|
10
|
+
Do the cheap confident work; escalate the rest.
|
|
11
|
+
|
|
12
|
+
Four unrelated lines of practice describe this same shape. Entity resolution
|
|
13
|
+
runs deterministic rules on records carrying an exact identifier and something
|
|
14
|
+
probabilistic on the remainder. Model cascades try the cheapest model and
|
|
15
|
+
escalate only what fails a threshold, reported at roughly half to four-fifths
|
|
16
|
+
off while holding most of the quality. Active learning scores without labels and
|
|
17
|
+
sends the least confident to a human. Tiered memory keeps cheaply and promotes
|
|
18
|
+
deliberately.
|
|
19
|
+
|
|
20
|
+
They are one pattern, and the payoff compounds: **the records the cheap tier
|
|
21
|
+
could not settle are simultaneously the escalation path and the queue worth a
|
|
22
|
+
human's attention** -- and once verified, the additions to the golden set. One
|
|
23
|
+
residue, three uses.
|
|
24
|
+
|
|
25
|
+
What separates a cascade from a router is that **the decision is made on the
|
|
26
|
+
output, not the input**. The cheap tier attempts the work and is then judged.
|
|
27
|
+
|
|
28
|
+
Which makes calibration the whole thing rather than a detail. Confidence scores
|
|
29
|
+
are typically miscalibrated, and a threshold tuned on one workload routinely
|
|
30
|
+
fails on the next, so a cascade without a measured error rate is a cost saving
|
|
31
|
+
with an unknown liability attached. Ruled out where a decision must be
|
|
32
|
+
explained: "the cheap path was confident" is not a reason anyone accepts.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: classical-ml
|
|
3
|
+
name: Classical ML
|
|
4
|
+
complexity: 1
|
|
5
|
+
components: [representation, reasoning]
|
|
6
|
+
applies_when:
|
|
7
|
+
- output_shape == classification
|
|
8
|
+
- output_shape == ranking
|
|
9
|
+
- output_shape == decision and labelled_count >= 1000
|
|
10
|
+
avoid_when: [output_shape == freeform, output_shape == structured]
|
|
11
|
+
evidence: {case_ids: [churn-scoring], confidence: high, last_verified: 2026-08-21}
|
|
12
|
+
---
|
|
13
|
+
Gradient-boosted trees and their relatives on tabular data.
|
|
14
|
+
|
|
15
|
+
Still the right answer for a numeric or class outcome from columns, and it wins
|
|
16
|
+
on the three axes that usually decide: it trains on far less data, it answers in
|
|
17
|
+
single-digit milliseconds, and it can say which features moved the prediction.
|
|
18
|
+
|
|
19
|
+
That last one is often decisive rather than nice to have. A requirement to
|
|
20
|
+
explain a decision to a regulator rules out approaches that cannot produce a
|
|
21
|
+
reason, whatever their accuracy.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: compose
|
|
3
|
+
name: Compose
|
|
4
|
+
complexity: 1
|
|
5
|
+
components: [deployment]
|
|
6
|
+
applies_when: [container_competence == true]
|
|
7
|
+
avoid_when: [existing_cluster == true, container_competence == false]
|
|
8
|
+
evidence: {case_ids: [studio-style], confidence: high, last_verified: 2026-08-25}
|
|
9
|
+
---
|
|
10
|
+
Several containers on one host, declared together.
|
|
11
|
+
|
|
12
|
+
The right rung for more than one long-lived process where multi-node scheduling
|
|
13
|
+
is not required. Isolation and reproducible dependencies without a control
|
|
14
|
+
plane, an etcd or an upgrade treadmill.
|
|
15
|
+
|
|
16
|
+
Its limit is honest and worth stating up front: one host. When that host is
|
|
17
|
+
being restarted, the service is down, and if that is unacceptable the next rung
|
|
18
|
+
is the answer rather than a workaround here.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: decision-log
|
|
3
|
+
name: Decision log
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [accountability]
|
|
6
|
+
applies_when: [interpretability_required == true]
|
|
7
|
+
avoid_when:
|
|
8
|
+
- output_shape == freeform
|
|
9
|
+
- output_shape == classification
|
|
10
|
+
- output_shape == ranking
|
|
11
|
+
evidence: {case_ids: [structured-extraction], confidence: high, last_verified: 2026-08-25}
|
|
12
|
+
---
|
|
13
|
+
Every decision kept with its inputs and the rule that produced it.
|
|
14
|
+
|
|
15
|
+
Enough where the decision came from a rule: replaying the rule against the
|
|
16
|
+
recorded inputs reproduces the outcome exactly, which is the strongest form of
|
|
17
|
+
explanation available and needs no model to generate it.
|
|
18
|
+
|
|
19
|
+
Not enough where the decision came from a model. There, the inputs and the
|
|
20
|
+
outcome do not reconstruct the reasoning, and something that attributes the
|
|
21
|
+
outcome to its drivers is required instead.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: deterministic-masking
|
|
3
|
+
name: Deterministic masking
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [redaction]
|
|
6
|
+
applies_when: [sensitivity_present == true]
|
|
7
|
+
avoid_when: [sensitivity_present == false]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-08-30}
|
|
9
|
+
---
|
|
10
|
+
Named fields replaced by stable hashes, before anything downstream sees the
|
|
11
|
+
record.
|
|
12
|
+
|
|
13
|
+
Deterministic on purpose, twice over. The same value masks to the same token,
|
|
14
|
+
so joins and deduplication survive masking -- a random mask would quietly
|
|
15
|
+
break every downstream equality. And the field list is declared, not
|
|
16
|
+
detected: a model guessing which fields are sensitive is a model that will
|
|
17
|
+
one day guess wrong in the direction that matters, so the list comes from the
|
|
18
|
+
contract the client's own samples marked and the FDE confirmed.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: deterministic
|
|
3
|
+
name: Deterministic
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [representation]
|
|
6
|
+
applies_when: [output_shape == structured, output_shape == decision]
|
|
7
|
+
avoid_when:
|
|
8
|
+
- output_shape == freeform
|
|
9
|
+
- output_shape == ranking
|
|
10
|
+
- cheap_path_coverage < 0.95
|
|
11
|
+
evidence: {case_ids: [structured-extraction], confidence: high, last_verified: 2026-08-21}
|
|
12
|
+
---
|
|
13
|
+
Entity masters, regular expressions, generated code, explicit mappings.
|
|
14
|
+
|
|
15
|
+
Where correctness is not negotiable -- mapping a field, deriving a figure,
|
|
16
|
+
resolving an identifier -- this is the right tool and a model is not. "The
|
|
17
|
+
model will handle it" is the wrong answer in a regulated setting, and it is
|
|
18
|
+
usually the wrong answer everywhere else that a rule can be written down.
|
|
19
|
+
|
|
20
|
+
Right where it covers the work. Where a meaningful share of records carry no
|
|
21
|
+
exact identifier, rules alone finish the ones they can and drop the rest
|
|
22
|
+
quietly -- which is why coverage is asked rather than assumed.
|
|
23
|
+
|
|
24
|
+
Cheapest to run, cheapest to explain, and it fails loudly rather than
|
|
25
|
+
plausibly. Reach past it only when the mapping genuinely cannot be stated.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: direct-call
|
|
3
|
+
name: Direct call
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [integration]
|
|
6
|
+
applies_when: [external_systems < 2]
|
|
7
|
+
avoid_when: [external_systems > 1]
|
|
8
|
+
evidence: {case_ids: [churn-scoring], confidence: high, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
One system, called directly. A registry for a single endpoint is ceremony.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: episodic-store
|
|
3
|
+
name: Episodic store
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [memory]
|
|
6
|
+
applies_when: [recall_span == across_sessions]
|
|
7
|
+
avoid_when: [recall_span == within_turn, recall_span == within_session]
|
|
8
|
+
evidence: {case_ids: [studio-style], confidence: medium, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
What the system learned, kept beyond the session that produced it.
|
|
11
|
+
|
|
12
|
+
A different system from working state, with a different write policy, and it
|
|
13
|
+
fails differently: a wrong belief written here is permanent and will be recalled
|
|
14
|
+
with confidence. What gets promoted from working state to long-term is the
|
|
15
|
+
decision that matters, and it should be deliberate rather than automatic.
|
|
16
|
+
|
|
17
|
+
Holds client data by definition, so it inherits residency -- embeddings too.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: explainability-record
|
|
3
|
+
name: Explainability record
|
|
4
|
+
complexity: 1
|
|
5
|
+
components: [accountability]
|
|
6
|
+
applies_when: [interpretability_required == true]
|
|
7
|
+
avoid_when: [interpretability_required == false]
|
|
8
|
+
evidence: {case_ids: [churn-scoring], confidence: high, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
Every decision keeps what drove it, in a form somebody outside the team can read
|
|
11
|
+
months later.
|
|
12
|
+
|
|
13
|
+
Built in from the start or not at all: reconstructing why a model decided
|
|
14
|
+
something after the fact is guesswork wearing a report's formatting.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: field-match
|
|
3
|
+
name: Field-level matching
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [evaluation]
|
|
6
|
+
applies_when: [output_shape == structured]
|
|
7
|
+
avoid_when: [output_shape == freeform]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: high, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
Compare each field against a verified answer. Exact where the field is exact,
|
|
11
|
+
tolerant where it is a date or an amount.
|
|
12
|
+
|
|
13
|
+
Gives a per-field breakdown rather than one number, which is what tells you
|
|
14
|
+
what to build next. Eighty-eight percent accurate says how often you fail; the
|
|
15
|
+
shape of the twelve percent says why.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: finetune
|
|
3
|
+
name: Fine-tuning
|
|
4
|
+
complexity: 3
|
|
5
|
+
components: [reasoning, representation]
|
|
6
|
+
applies_when: [output_shape == freeform and labelled_count >= 1000]
|
|
7
|
+
avoid_when: [output_shape == classification, output_shape == decision]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
Adapting a model's behaviour: tone, house style, output shape, schema mapping.
|
|
11
|
+
|
|
12
|
+
**For behaviour, never for facts.** Fine-tuning teaches a model *how* to
|
|
13
|
+
respond, not *what* is true; anything that changes weekly belongs in retrieval,
|
|
14
|
+
not in weights. Train only on verified pairs -- unverified rows are an asset,
|
|
15
|
+
but they are mined rather than trained on.
|
|
16
|
+
|
|
17
|
+
**Reached by graduation or override, never by the first decision.** The
|
|
18
|
+
prompted model is simpler and applies wherever this does, so
|
|
19
|
+
simplest-first always chooses it first -- which is this corpus's own
|
|
20
|
+
rule: try the model before adapting it, and let the measured gap argue
|
|
21
|
+
for adaptation. Until calibrated graduation triggers exist, the road
|
|
22
|
+
here is `fde override`, with the measured gap as the reason.
|
|
23
|
+
|
|
24
|
+
The label count is in the applies condition because it is the whole question:
|
|
25
|
+
adaptation without enough verified pairs is not available, whatever the output
|
|
26
|
+
shape, and an approach that never asked how many labels exist would recommend
|
|
27
|
+
training on hope.
|
|
28
|
+
|
|
29
|
+
Expensive to reverse: a change means retraining and re-evaluating. Earn it.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: fixed-sequence
|
|
3
|
+
name: Fixed sequence
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [planning]
|
|
6
|
+
applies_when: [always]
|
|
7
|
+
avoid_when: [output_shape == decision]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: high, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
Steps written in advance, in order, by a person.
|
|
11
|
+
|
|
12
|
+
Every path is enumerable, so every path can be tested. Cost and latency are
|
|
13
|
+
bounded at design time rather than discovered in production. Where the work
|
|
14
|
+
genuinely has a fixed shape this is not a lesser option, it is the correct one,
|
|
15
|
+
and reaching past it is how a pipeline acquires a control loop it never needed.
|
|
16
|
+
|
|
17
|
+
The question worth asking is not whether this counts as an agent. It is whether
|
|
18
|
+
the next step can depend on the last one in a way nobody enumerated -- and if
|
|
19
|
+
it cannot, this is the answer.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: gitops
|
|
3
|
+
name: Manifests in version control
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [provisioning]
|
|
6
|
+
applies_when: [existing_cluster == true]
|
|
7
|
+
avoid_when: [existing_cluster == false]
|
|
8
|
+
evidence: {case_ids: [route-planning], confidence: medium, last_verified: 2026-08-25}
|
|
9
|
+
---
|
|
10
|
+
The desired state in a repository, reconciled onto a cluster that already exists.
|
|
11
|
+
|
|
12
|
+
"Neither provisioner" as a real answer. Where the infrastructure is somebody
|
|
13
|
+
else's problem, adding one provisions nothing and gives an FDE a second thing to
|
|
14
|
+
hand over.
|
|
15
|
+
|
|
16
|
+
What it buys instead is that the deployed state is reviewable and revertable by
|
|
17
|
+
whoever already reviews changes, which is usually the property people wanted
|
|
18
|
+
from a provisioning tool in the first place.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: governed-tools
|
|
3
|
+
name: Governed tool boundary
|
|
4
|
+
complexity: 1
|
|
5
|
+
components: [integration]
|
|
6
|
+
applies_when: [external_systems > 1]
|
|
7
|
+
avoid_when: [external_systems < 2]
|
|
8
|
+
evidence: {case_ids: [route-planning], confidence: high, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
One entry point through which every outward call passes, each tool declaring a
|
|
11
|
+
typed schema, the scope it requires, and whether it changes anything.
|
|
12
|
+
|
|
13
|
+
Past the first system this stops being tidiness: it is the only place
|
|
14
|
+
authentication, authorisation and audit can be enforced once instead of per
|
|
15
|
+
caller. The mutative flag is what lets the autonomy move find the steps needing
|
|
16
|
+
a gate and an idempotency key, without anyone remembering to add them.
|
|
17
|
+
|
|
18
|
+
An unregistered tool cannot be called. That is the property, not a policy.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: graph-retrieval
|
|
3
|
+
name: Graph retrieval
|
|
4
|
+
complexity: 3
|
|
5
|
+
components: [retrieval]
|
|
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-08-21}
|
|
9
|
+
---
|
|
10
|
+
Explicit entities and edges, traversed at query time.
|
|
11
|
+
|
|
12
|
+
Worth its cost only where similarity search structurally cannot answer -- how
|
|
13
|
+
two things connect, rather than which text resembles a query. On single-fact
|
|
14
|
+
lookup it measurably loses to plain chunks, so this is a specialised instrument
|
|
15
|
+
rather than an upgrade.
|
|
16
|
+
|
|
17
|
+
The costs are real: multi-pass extraction to build it, two to three times the
|
|
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.
|
|
20
|
+
|
|
21
|
+
Published gains also warrant scepticism -- judge position bias has been shown to
|
|
22
|
+
swing reported win rates by tens of points. Measure on your own traffic.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: judged
|
|
3
|
+
name: Judged
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [evaluation]
|
|
6
|
+
applies_when: [output_shape == freeform]
|
|
7
|
+
avoid_when: [output_shape == structured, output_shape == classification]
|
|
8
|
+
evidence: {case_ids: [studio-style], confidence: medium, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
A model grades the output against a rubric, calibrated against human agreement
|
|
11
|
+
before anyone trusts it.
|
|
12
|
+
|
|
13
|
+
Two rules. The author never grades itself. And where nothing may leave, the
|
|
14
|
+
judge runs locally -- a metric that needs a hosted model is not a metric you
|
|
15
|
+
have, and finding that out at deployment is too late.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: keyword-search
|
|
3
|
+
name: Keyword search
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [retrieval]
|
|
6
|
+
applies_when: [query_pattern == lookup]
|
|
7
|
+
avoid_when: [query_pattern == multi_hop]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: high, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
Lexical matching. Unfashionable, cheap, and hard to beat when people search for
|
|
11
|
+
terms that actually appear -- identifiers, part numbers, names.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: kubernetes-manifests
|
|
3
|
+
name: Cluster manifests
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [deployment]
|
|
6
|
+
applies_when: [existing_cluster == true, external_systems > 2]
|
|
7
|
+
avoid_when: [container_competence == false and existing_cluster == false]
|
|
8
|
+
evidence: {case_ids: [route-planning], confidence: high, last_verified: 2026-08-25}
|
|
9
|
+
---
|
|
10
|
+
Manifests applied to a cluster that already exists.
|
|
11
|
+
|
|
12
|
+
Cheap when the cluster is there and somebody else patches it -- the tenth
|
|
13
|
+
workload costs almost nothing, which is the entire argument for a platform.
|
|
14
|
+
|
|
15
|
+
Expensive when it is not. Standing up a cluster for one deployment buys a
|
|
16
|
+
control plane, an upgrade cadence and a set of failure modes for something that
|
|
17
|
+
wanted a service unit, and the cost lands on whoever is still there in a year.
|
|
18
|
+
|
|
19
|
+
Competence gates this only where no cluster exists yet. A cluster already running means somebody operates it -- manifests are how that shop deploys, whatever this team's container practice, and blocking the only cluster-native option on the applying team's skills would leave a cluster shop with no way to deploy at all.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: labelled-metrics
|
|
3
|
+
name: Labelled metrics
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [evaluation]
|
|
6
|
+
applies_when: [output_shape == classification, output_shape == ranking, output_shape == decision]
|
|
7
|
+
avoid_when: [output_shape == freeform, output_shape == structured]
|
|
8
|
+
evidence: {case_ids: [churn-scoring], confidence: high, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
Precision, recall and their relatives against held-out labels.
|
|
11
|
+
|
|
12
|
+
Pick the metric from the cost of each error, not from convention. Where a false
|
|
13
|
+
negative costs a hundred times a false positive, accuracy is the wrong number
|
|
14
|
+
and will look fine while the system fails.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: llm-extraction
|
|
3
|
+
name: Model extraction
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [representation]
|
|
6
|
+
applies_when: [output_shape == structured]
|
|
7
|
+
avoid_when: [interpretability_required == true]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-08-27}
|
|
9
|
+
---
|
|
10
|
+
A model decoding raw records into the declared contract.
|
|
11
|
+
|
|
12
|
+
Split from the prompted-model approach deliberately, because the claim is
|
|
13
|
+
narrower than "use a model": this is a *representation* move, it exists only
|
|
14
|
+
where there is a contract to decode into, and freeform output has none. An
|
|
15
|
+
approach whose applicability differs by component is two approaches wearing
|
|
16
|
+
one name, and the seam always shows at the worst moment.
|
|
17
|
+
|
|
18
|
+
The opening move for extraction before anything has been measured -- the
|
|
19
|
+
deterministic path needs coverage nobody has counted and the cascade needs
|
|
20
|
+
calibration that does not exist yet. Behind the same Mapper interface the
|
|
21
|
+
deterministic path satisfies, so graduating when the numbers arrive is a
|
|
22
|
+
swap, not a redesign.
|
|
23
|
+
|
|
24
|
+
Avoided where interpretability is required: a mapping that cannot say why it
|
|
25
|
+
mapped is precisely what that requirement forbids, and the deterministic
|
|
26
|
+
path is the interpretable one.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: llm-scrubbing
|
|
3
|
+
name: Model-assisted scrubbing
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [redaction]
|
|
6
|
+
applies_when: [sensitivity_present == true]
|
|
7
|
+
avoid_when: [sensitivity_present == false, data_residency == cannot_leave]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: low, last_verified: 2026-08-30}
|
|
9
|
+
---
|
|
10
|
+
A model rewrites free text with the identifying entities removed, for the
|
|
11
|
+
case field-level masking cannot reach: a name living *inside* a narrative
|
|
12
|
+
field, not in a field of its own.
|
|
13
|
+
|
|
14
|
+
Never the first decision -- deterministic masking is simpler and wins where
|
|
15
|
+
the sensitive material is field-shaped, which is the common case and the
|
|
16
|
+
measurable one. Reached by override when the sample pairs show identifiers
|
|
17
|
+
inside prose, and carrying its own irony to manage: the scrubbing model sees
|
|
18
|
+
the unscrubbed text, so on a boundary engagement it must run inside -- and
|
|
19
|
+
where data cannot leave at all, the boundary already holds everything and
|
|
20
|
+
this approach is avoided outright.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: llm
|
|
3
|
+
name: Prompted model
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [reasoning]
|
|
6
|
+
applies_when: [output_shape == freeform, output_shape == structured]
|
|
7
|
+
avoid_when: [output_shape == classification, output_shape == decision]
|
|
8
|
+
evidence: {case_ids: [studio-style], confidence: medium, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
A capable model, prompted, with no adaptation.
|
|
11
|
+
|
|
12
|
+
The right first move for open-ended generation, and the fastest thing to stand
|
|
13
|
+
up. Try it before fine-tuning: the gap it leaves is what tells you whether
|
|
14
|
+
adaptation is worth its cost.
|
|
15
|
+
|
|
16
|
+
The same holds for structured output, where the model decodes into a declared
|
|
17
|
+
schema. This is the standard opening move for extraction before anything has
|
|
18
|
+
been measured -- the cascade needs calibration that does not exist yet, and
|
|
19
|
+
the deterministic path needs coverage nobody has counted. Start here, measure,
|
|
20
|
+
then graduate.
|
|
21
|
+
|
|
22
|
+
Swapping the model rarely fixes a wrong answer -- it changes the tone of the
|
|
23
|
+
wrong answer. When quality is capped, look upstream at what the model was given.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: local-embedding
|
|
3
|
+
name: Local embeddings
|
|
4
|
+
complexity: 1
|
|
5
|
+
components: [embedding]
|
|
6
|
+
applies_when: [data_residency == cannot_leave, hosting == air-gapped, hosting == on-prem]
|
|
7
|
+
avoid_when: [operates_after_handover == nobody_yet and data_residency == may_leave]
|
|
8
|
+
evidence: {case_ids: [structured-extraction], confidence: high, last_verified: 2026-08-25}
|
|
9
|
+
---
|
|
10
|
+
An embedding model running inside the boundary.
|
|
11
|
+
|
|
12
|
+
Chosen because something forbids the alternative rather than because it is
|
|
13
|
+
better. Small embedding models are cheap to run and unremarkable to operate,
|
|
14
|
+
which makes this a far lighter obligation than self-hosting a generation model
|
|
15
|
+
-- but it is still a model somebody has to keep running after the engagement
|
|
16
|
+
ends.
|
|
17
|
+
|
|
18
|
+
Ruled out where nobody is named to operate it. A model with no owner is a
|
|
19
|
+
liability handed over with a bow on it, and an embedding model whose host dies
|
|
20
|
+
takes the index with it.
|
|
21
|
+
|
|
22
|
+
The handover concern is stated precisely rather than broadly: with nobody
|
|
23
|
+
named to operate and data free to leave, the managed alternative is
|
|
24
|
+
strictly simpler and wins. But where data cannot leave, the plain
|
|
25
|
+
realization is an in-process library call whose operational burden is the
|
|
26
|
+
application's own -- the broad version of this avoid once treated a
|
|
27
|
+
library import like a GPU fleet, and stranded every engagement inside a
|
|
28
|
+
boundary.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: managed-api
|
|
3
|
+
name: Managed API
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [serving]
|
|
6
|
+
applies_when: [data_residency == may_leave]
|
|
7
|
+
avoid_when:
|
|
8
|
+
- data_residency == cannot_leave
|
|
9
|
+
- hosting == air-gapped
|
|
10
|
+
- hosting == on-prem
|
|
11
|
+
- human_waiting == no and corpus_size > 100000
|
|
12
|
+
- human_waiting == no and arrival_rate > 50000
|
|
13
|
+
- latency_budget_ms < 100
|
|
14
|
+
evidence: {case_ids: [studio-style], confidence: high, last_verified: 2026-08-21}
|
|
15
|
+
---
|
|
16
|
+
Somebody else's endpoint, paid per token.
|
|
17
|
+
|
|
18
|
+
A p95 budget under a hundred milliseconds cannot be met across somebody
|
|
19
|
+
else's network: the round trip and their queue are spent before any work
|
|
20
|
+
happens. That is a physics objection, not a pricing one, which is why it is
|
|
21
|
+
a rule here rather than a note in the costing.
|
|
22
|
+
|
|
23
|
+
The volume objection is really about flow, not stock: fifty thousand
|
|
24
|
+
requests a day with nobody waiting is sustained work that rented GPUs do
|
|
25
|
+
for a fraction of per-token pricing, whatever the archive size says.
|
|
26
|
+
|
|
27
|
+
The cheapest way to be wrong cheaply: no infrastructure, no cold start, nothing
|
|
28
|
+
to operate. Sustained high-volume interactive traffic is where it stays cheapest
|
|
29
|
+
too, because self-hosting the same load means paying for redundancy and peak
|
|
30
|
+
headroom around the clock.
|
|
31
|
+
|
|
32
|
+
It stops being the cheapest option on high-volume work with nobody waiting:
|
|
33
|
+
per-token pricing at that scale runs several times what rented GPUs cost for
|
|
34
|
+
the same job, and the cold start nobody is waiting through costs nothing.
|
|
35
|
+
|
|
36
|
+
Sending data here is one-way. You cannot un-send it, which is a different
|
|
37
|
+
category of decision from an expensive one.
|
|
38
|
+
|
|
39
|
+
Provider prompt caching changes the arithmetic before any sizing does: reused
|
|
40
|
+
prompt prefixes bill at a fraction of the input rate, but only on exact token
|
|
41
|
+
match. That makes prompt hygiene a production concern, not an optimisation --
|
|
42
|
+
variable content (timestamps, user names) placed early in the prompt
|
|
43
|
+
invalidates every cached block after it, and rewriting history (summarising)
|
|
44
|
+
re-bills the whole prefix where trimming it in place stays byte-identical. A
|
|
45
|
+
semantic cache is a different animal: it returns stored responses on
|
|
46
|
+
similarity, skips the model entirely, and can return a confidently wrong
|
|
47
|
+
answer with a success status -- a sentence and its negation embed close
|
|
48
|
+
together. It is a retrieval system wearing a cache's name, and it needs the
|
|
49
|
+
same evaluation any retrieval gets.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: managed-embedding
|
|
3
|
+
name: Managed embeddings
|
|
4
|
+
complexity: 0
|
|
5
|
+
components: [embedding]
|
|
6
|
+
applies_when: [data_residency == may_leave]
|
|
7
|
+
avoid_when:
|
|
8
|
+
- data_residency == cannot_leave
|
|
9
|
+
- hosting == air-gapped
|
|
10
|
+
- hosting == on-prem
|
|
11
|
+
evidence: {case_ids: [studio-style], confidence: high, last_verified: 2026-08-25}
|
|
12
|
+
---
|
|
13
|
+
A vendor endpoint. Nothing to host, nothing to keep warm, and generally better
|
|
14
|
+
quality per unit of effort than anything self-hosted at small scale.
|
|
15
|
+
|
|
16
|
+
Ruled out wherever the text may not leave, and for the reason people find
|
|
17
|
+
surprising: sending an embedding is sending the text. Vectors are recoverable
|
|
18
|
+
to their source, so this is not a way of anonymising anything on the way out.
|
|
19
|
+
|
|
20
|
+
One-way, like any vendor call. And expensive to reverse for a second reason --
|
|
21
|
+
changing embedding model means reindexing everything, so leaving is a
|
|
22
|
+
reindexing project rather than a configuration change.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: manual-runbook
|
|
3
|
+
name: Written steps
|
|
4
|
+
complexity: 2
|
|
5
|
+
components: [provisioning]
|
|
6
|
+
applies_when: [always]
|
|
7
|
+
avoid_when:
|
|
8
|
+
- existing_cluster == true
|
|
9
|
+
evidence: {case_ids: [structured-extraction], confidence: medium, last_verified: 2026-08-25}
|
|
10
|
+
---
|
|
11
|
+
Steps somebody follows, written down.
|
|
12
|
+
|
|
13
|
+
The floor, and what nothing-known resolves to. Automating a deployment before
|
|
14
|
+
anyone has performed it once tends to automate a guess -- and a runbook that has
|
|
15
|
+
been followed successfully is the only honest input to a playbook worth writing.
|
|
16
|
+
|
|
17
|
+
Not a permanent answer. It is the rung that costs least to be wrong about, and
|
|
18
|
+
it graduates as soon as the environment is understood well enough that repeating
|
|
19
|
+
the steps is tedious rather than instructive.
|
|
20
|
+
|
|
21
|
+
Ruled out where the team already runs something. Handing a written procedure to
|
|
22
|
+
a shop with an existing tool is asking them to do by hand what they already
|
|
23
|
+
automate.
|
|
24
|
+
|
|
25
|
+
Complexity 2, not 0, and the number is the design: complexity orders by
|
|
26
|
+
cost of ownership, and a runbook is recurring human labour forever --
|
|
27
|
+
every automated tool that applies beats it on that measure, which is the
|
|
28
|
+
preference expressed without a single avoid rule. When the better tools
|
|
29
|
+
are blocked (an Ansible shop with an ephemeral environment, a Terraform
|
|
30
|
+
shop with no API), nothing avoids the runbook, and the floor holds.
|
|
31
|
+
Ephemeral by hand is painful and is said so here; painful is not the same
|
|
32
|
+
as impossible.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: model-planner
|
|
3
|
+
name: Model planner
|
|
4
|
+
complexity: 3
|
|
5
|
+
components: [planning]
|
|
6
|
+
applies_when: [output_shape == decision, recall_span == across_sessions]
|
|
7
|
+
avoid_when: [interpretability_required == true]
|
|
8
|
+
evidence: {case_ids: [route-planning], confidence: low, last_verified: 2026-08-21}
|
|
9
|
+
---
|
|
10
|
+
The model decomposes the goal at run time and chooses what to do next.
|
|
11
|
+
|
|
12
|
+
This is the line worth drawing. Once the next step can depend on the last in a
|
|
13
|
+
way nobody enumerated, paths stop being testable and cost stops being bounded --
|
|
14
|
+
so crossing it obliges three things a fixed sequence never needed: a step cap, a
|
|
15
|
+
budget cap, and a critic before anything irreversible.
|
|
16
|
+
|
|
17
|
+
Ruled out where a decision must be explained. A plan invented at run time is
|
|
18
|
+
hard to defend afterwards, and "the model decided" is not a reason a regulator
|
|
19
|
+
accepts.
|