9.7 KiB
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 instruction pack executed by an existing host. 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 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 host/model adapter | Profile discovery, model capabilities, tool access and execution metadata | Change configured host/model without baking provider syntax into shared skills. The host owns its provider SDK. |
| Agent pipeline coordinator | Stage inputs/outputs, work budget, checkpoints and outcomes | Replace coordinating instructions while preserving skill contracts and resume obligations. The initial coordinator is host-executed Markdown, not a standalone engine. |
| 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 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. Local-agent helper/connector code 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 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
- Identify the public contract and current behavioral fixtures. Add missing fixtures for the changed boundary before declaring equivalence.
- 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.
- Run shared contract tests, consumer integration tests and import-boundary checks. Test required failure states, cancellation and denied capabilities, not only successful outputs.
- 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.
- 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.
- 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. The canonical repository port now owns its stable errors, path rules, revision-history semantics and a shared behavioral contract run against both the Git adapter and an independent in-memory implementation. CanonicalNodeReader also returns the same accepted node and citations against the substitute without consumer changes. This demonstrates dependency isolation and the checked contract subset; it does not establish durability, locking, crash recovery or production equivalence for another backend. Broader fault, concurrency and filesystem-specific qualification remains required.