test(architecture): freeze direct adapter debt

This commit is contained in:
jxxghp
2026-08-27 06:06:14 +08:00
parent e1483e85dc
commit 2553226f37
12 changed files with 461 additions and 86 deletions
+14 -2
View File
@@ -177,7 +177,10 @@ the plugin SDK.
RSS is not classified as a transport adapter merely because it uses HTTP. The
current `RssHelper` combines feed parsing, torrent item semantics, configured
site-specific URL discovery and browser fallback, so it belongs to
`app/application/rss.py` and consumes network adapters. Likewise, the generated
`app/application/rss.py`. The target design gives it ownership of the required
technical Ports and lets startup inject network/system Adapter implementations.
Its current concrete imports are tracked as `S2-L6` temporary debt, not an
approved dependency direction. Likewise, the generated
site extension owns the configured catalog/authentication/index capability and
lives in `app/application/site/`; only its download and file installation
mechanism remains in `app/adapters/system/resource.py`.
@@ -516,12 +519,21 @@ The target remains zero canonical host cycles except the precisely contained
vendor component. A temporary policy entry is an executable migration obligation,
not precedent for approving another cycle.
The same fact/policy split governs direct Adapter imports. The generated
dependency baseline records the original runtime imports from `app.application`
and `app.chain` without parent-package expansion. Every current edge is an exact
`temporary_debt` entry in dependency policy with a removal leaf; the target state
is empty. New or replacement edges and stale policy entries fail. Application owns
the Port required by its use case, startup injects the concrete Adapter, and Chain
consumes the Application capability or an injected Port. A `canonical capability`
never means permission to import a concrete `app.adapters.*` implementation.
## Permitted Call Directions
| Direction | Status |
|---|---|
| `entrypoint -> chain / application / injected persistence Port` | Allowed according to workflow complexity |
| `chain -> module (only via run_module dispatch) / application / injected Port / canonical capability` | Allowed; direct `chain -> module` and `chain -> Oper` imports forbidden |
| `chain -> module (only via run_module dispatch) / application / injected Port / canonical capability` | Allowed; direct `chain -> module`, `chain -> Oper` and `chain -> concrete adapter` imports forbidden |
| `chain -> agent implementation` | Forbidden; chains reach Agent runtime only through `app/application/agent.py`; `app/startup/initializers/agent.py` registers lightweight providers at import time, and implementations are materialized only when the capability is enabled or first used |
| `agent.tools -> api / scheduler / command` | Forbidden; tools use `app/application/plugin/routes.py`, `plugin/folders.py`, `scheduling.py` and `commands.py` application services |
| `api -> factory` | Forbidden; the FastAPI route adapter is injected into `app/application/plugin/routes.py` by the composition root after creation |
+6 -1
View File
@@ -2,7 +2,11 @@
## HTTP Client Conventions
**Rule:** Host outbound HTTP requests must go through `RequestUtils` from `app/adapters/network/http.py`. Plugins import it from `app.sdk.network`. Do not use `requests`, `httpx`, or `aiohttp` directly.
**Rule:** Host outbound HTTP transport implementations must go through `RequestUtils` from
`app/adapters/network/http.py`. This transport rule does not authorize Application or Chain to
import the concrete Adapter; they own/use a Port and receive its implementation from startup.
Plugins import the curated facade from `app.sdk.network`. Do not use `requests`, `httpx`, or
`aiohttp` directly outside a separately reviewed SDK, streaming, or vendored transport boundary.
`RequestUtils` handles:
- Proxy configuration (from `settings.PROXY_*`)
@@ -12,6 +16,7 @@
- Retry logic
```python
# Adapter implementation example; Application/Chain consume an injected Port instead.
from app.adapters.network.http import RequestUtils
res = RequestUtils(