Purpose
Adopt the red-team disposition for future provider/plugin modularity without adding a plugin ecosystem to the MVP critical path.
Decision
NARROW: posture provider-specific code behind a small in-tree adapter boundary now; defer Pluggy, entry-point discovery, separately distributed wheels, compatibility negotiation, package templates, and a general plugin manager.
The first proven boundary is deliberately narrow: captured provider evidence -> normalized Foundry observation. Do not invent an all-purpose ProviderPlugin interface spanning observation, acquisition, runtime loading, policy, qualification, and deployment.
Why this is on-path beneficial
- keeps provider-specific semantics and future SDK types out of core control logic;
- makes deterministic fixture testing easier;
- preserves explicit provider selection/authorization rather than auto-loading installed code;
- allows later extraction to a separate wheel with minimal architecture surgery if evidence supports it;
- does not create a new release/compatibility matrix before the first consumer is proven.
Implementation increment
Stack on the existing HF observation work from #24 / draft PR #25.
- Define one stdlib-only provider evidence adapter protocol for normalization.
- Move Hugging Face-specific normalization into an in-tree HF adapter implementing that protocol.
- Keep the existing
normalize_hf_observation.py CLI/API behavior backward-compatible as a thin wrapper.
- Add deterministic contract tests proving the adapter identity/capability surface and equivalence of wrapper vs direct adapter output.
- Document future extraction criteria and non-goals.
Explicit non-goals
Do not add:
- Pluggy;
- Python entry-point discovery;
- separate provider wheels/repos;
- provider auto-discovery;
- generic plugin lifecycle/version negotiation;
- plugin permission manifests/sandbox claims;
- runtime/target/representation plugin families;
- changes to Foundry selection policy or project validators;
- provider acquisition/materialization beyond the currently proven increment.
A separately installed Python wheel is a packaging/capability boundary, not a security sandbox.
Future extraction gate
Do not create a separately distributed provider wheel until at least a second real implementation has exercised the same boundary and one or more material extraction triggers exist, such as independent release cadence, substantial exclusive dependencies, dependency conflict, deliberately omitted deployments, different maintenance ownership, or independent reuse.
If the second implementation does not fit naturally, revise the in-tree seam rather than preserving a premature public plugin API.
R4
- reproducible: stdlib-only deterministic fixtures/tests;
- repeatable: no provider/network/model access;
- reversible: one stacked adapter refactor with wrapper compatibility;
- idempotent: repeated normalization remains byte-deterministic.
Related: #18, #19, #24, draft PRs #22/#23/#25; SemperSupra/desktop-ui-cv#17/#19.
Purpose
Adopt the red-team disposition for future provider/plugin modularity without adding a plugin ecosystem to the MVP critical path.
Decision
NARROW: posture provider-specific code behind a small in-tree adapter boundary now; defer Pluggy, entry-point discovery, separately distributed wheels, compatibility negotiation, package templates, and a general plugin manager.
The first proven boundary is deliberately narrow: captured provider evidence -> normalized Foundry observation. Do not invent an all-purpose
ProviderPlugininterface spanning observation, acquisition, runtime loading, policy, qualification, and deployment.Why this is on-path beneficial
Implementation increment
Stack on the existing HF observation work from #24 / draft PR #25.
normalize_hf_observation.pyCLI/API behavior backward-compatible as a thin wrapper.Explicit non-goals
Do not add:
A separately installed Python wheel is a packaging/capability boundary, not a security sandbox.
Future extraction gate
Do not create a separately distributed provider wheel until at least a second real implementation has exercised the same boundary and one or more material extraction triggers exist, such as independent release cadence, substantial exclusive dependencies, dependency conflict, deliberately omitted deployments, different maintenance ownership, or independent reuse.
If the second implementation does not fit naturally, revise the in-tree seam rather than preserving a premature public plugin API.
R4
Related: #18, #19, #24, draft PRs #22/#23/#25;
SemperSupra/desktop-ui-cv#17/#19.