67 lines
9.0 KiB
Markdown
67 lines
9.0 KiB
Markdown
# Module design and replacement protocol
|
|
|
|
13 October 2026. Requirement confirmed by the owner: all development must be modular so each module can be updated or replaced by a better implementation. This protocol applies to the service, local agent, skills, pipelines, connector and frontend. It makes replacement an acceptance criterion.
|
|
|
|
## Default structure
|
|
|
|
Use a modular monolith for the service and a separate local-agent application. A module is a coherent responsibility with a public contract, private implementation and declared dependencies. It does not need its own process, repository or package release. Split deployment only when isolation, scaling or independent release needs justify it.
|
|
|
|
Every feature belongs to a named module. Consumers use its public interface; they cannot import private helpers, inspect its tables, edit its files or rely on provider-specific response objects. Cross-module payloads use GEWU-owned types. The composition root selects implementations and manages their lifetimes. Domain/application code cannot select a concrete implementation through scattered conditionals.
|
|
|
|
Internal pure helpers may remain functions. Add an interface at a real replaceable boundary, not around every function. Keep stable interfaces small enough that a replacement does not have to emulate unrelated features.
|
|
|
|
## Required module description
|
|
|
|
Each replaceable module has a short description beside its implementation, plus a machine-readable descriptor when configuration selects it. The description declares responsibility, public input/output types, errors, owned state, side effects, dependencies, lifecycle and resource limits. The descriptor declares `module_id`, implementation version, provided contract/version, required capabilities, compatible state-schema versions and configuration schema. Resolve exact implementation versions and artifact hashes in the release/run manifest.
|
|
|
|
Compatibility is behavioral: valid inputs, errors, cancellation, ordering, idempotency and security limits all belong to the contract. Matching method names or a version range alone is insufficient. [Python Protocols](https://docs.python.org/3.12/library/typing.html#typing.Protocol) and TypeScript interfaces describe structure; runtime validators and contract tests enforce exchanged data and behavior.
|
|
|
|
## Initial replacement boundaries
|
|
|
|
| Module boundary | Public contract owns | Private implementation / replacement example |
|
|
| --- | --- | --- |
|
|
| Service application use cases | Scope, authorization order, proposal/read outcomes | Reorganize orchestration without changing HTTP/MCP behavior. |
|
|
| Acceptance validators and policy evaluator | Required checks, typed findings, policy/authority bindings | Improve implementation while retaining mandatory evidence and authority invariants. No configurable bypass of those checks. |
|
|
| Canonical repository and publication | Committed reads, expected-head publication, manifests, reconciliation | Git implementation may change behind the port; abandoning Git authority requires an explicit architecture/product change. |
|
|
| Artifact and workflow stores | Immutable hashes, atomic records, resumable upload/run operations | Local filesystem storage can later gain an object-storage adapter. |
|
|
| Source parsers | Immutable extraction artifact and supported locator profile | Replace a PDF parser; keep old extraction artifacts and citations resolvable. |
|
|
| Embedding provider | Normalized vectors plus model/profile metadata | Replace model/runtime; rebuild a separate vector generation. |
|
|
| Search and ranking | Scoped candidates, scores/explanations, revision and budget rules | Replace FTS/vector engine or ranking algorithm without modifying readers. |
|
|
| Identity and credentials | Authenticated principal, capabilities, grants and revocation | Replace login backend without changing proposal authorization semantics. |
|
|
| MCP and HTTP adapters | Versioned wire schemas and domain-error mapping | Update transport SDK without moving rules into routes. |
|
|
| Agent model provider | Typed requests/results, usage, timeouts and declared capabilities | Change local/hosted provider without exposing SDK types to skills. |
|
|
| Agent pipeline runner | Stage dispatch, bounded scheduling, checkpoints and outcomes | Replace orchestration library while preserving stage contracts and resume semantics. |
|
|
| Skills and stage handlers | Declared inputs/outputs, tools, prompt/content versions and budget | Replace an extraction or assessment skill without rewriting the pipeline. |
|
|
| Harness adapter | Profile/skill discovery and authenticated public tool access | Change a host's configuration format without duplicating the skill pack. |
|
|
| Frontend feature modules | Route/data contract, component props, events and accessibility behavior | Replace an evidence viewer or result list while preserving API and navigation. |
|
|
| Design system | Semantic tokens and shared interaction primitives | Revise typography/theme centrally without recoloring feature implementations. |
|
|
|
|
## Versioning and dependency rules
|
|
|
|
Public contracts, implementation versions, persisted schemas and model/prompt artifacts have distinct identifiers. Use [semantic versioning](https://semver.org/) for declared stable contracts: compatible additions are minor, fixes are patch, breaking behavior is major. Before 1.0, explicitly list supported contract versions; do not assume every `0.x` update is compatible. Published immutable artifacts are never changed in place.
|
|
|
|
Backend boundaries use typed ports with injected dependencies; the frontend imports feature public exports and shared primitives. Shared contract packages stay small and have no dependency on providers, storage engines or UI frameworks. Reject import cycles and cross-feature private imports in CI. The local agent cannot import service storage/auth internals; its GEWU access is through the public MCP client contract.
|
|
|
|
Configuration selects from installed, reviewed implementations by ID. Validate configuration and capability compatibility before activation. Do not discover executable modules from uploaded sources, skill text, arbitrary import strings or URL-supplied code. Python package entry points are a possible future distribution mechanism, not permission to auto-load third-party code; [the packaging guide](https://packaging.python.org/en/latest/guides/creating-and-discovering-plugins/) describes discovery mechanisms, not trust enforcement.
|
|
|
|
Existing deployments use lockfiles and a release manifest. Agent runs additionally pin pipeline, stage, skill, provider and model versions at start. No automatic hot swap in a running acceptance transaction or reasoning stage. A newly selected implementation applies at a controlled deployment/run boundary.
|
|
|
|
## Replacement workflow
|
|
|
|
1. Identify the public contract and current behavioral fixtures. Add missing fixtures for the changed boundary before declaring equivalence.
|
|
2. Implement the replacement behind the same port. Compare old/new behavior on representative data; compare retrieval quality, evidence fidelity or performance where the module affects them. A fake adapter proves dependency isolation only, not production equivalence.
|
|
3. Run shared contract tests, consumer integration tests and import-boundary checks. Test required failure states, cancellation and denied capabilities, not only successful outputs.
|
|
4. Migrate state explicitly or build a new derived generation. Record schema compatibility, migration checks and rollback path. Retain old source/extraction versions and accepted receipts.
|
|
5. Activate through the composition root/configuration in a test deployment, then complete the affected native client/browser/recovery gates. A compatible swap should require no changes to consumers' business logic.
|
|
6. Roll back by selecting the previous implementation only if it can read the resulting state. Otherwise use the tested state migration/restore procedure. Never claim that changing a version number reverses a destructive migration.
|
|
|
|
A breaking contract change needs an ADR, explicit consumer migration, version negotiation where relevant, and a declared deprecation window. Replaceability does not imply every future technology will fit today's contract; preserve the product invariants and document the actual compatibility cost.
|
|
|
|
## Required evidence
|
|
|
|
At scaffolding, add import/dependency checks and reusable contract test suites for the first real boundaries. Each new module must demonstrate isolated testing with collaborators substituted through public ports. Each replacement must demonstrate a swap without unrelated module edits, or declare the contract migration that makes those edits necessary.
|
|
|
|
Early acceptance examples: swap an embedding provider and rebuild without changing search consumers; substitute an extraction-stage implementation while preserving old citations; replace a frontend evidence panel without changing the read API; resume an agent run with its original pinned skill version after a newer version is installed. These are required design tests to implement, not existing passes.
|
|
|
|
Primary documentation above was checked on 13 October 2026. No module implementation or replacement test exists yet.
|