chore(architecture): 同步模块路径与质量门禁

This commit is contained in:
jxxghp
2026-09-16 00:12:16 +08:00
parent 4e9a64c0f0
commit b99b4fe2c3
20 changed files with 135 additions and 50 deletions

View File

@@ -76,8 +76,8 @@ The legacy roots have no physical directories in the source tree. Current images
| `app/adapters/cache/` | Redis 与文件缓存等具体持久化实现 | 缓存协议、装饰器和进程内缓存策略 | `backends.py`, `redis.py` |
| `app/adapters/system/` | 操作系统、文件、进程、标准流、包/资源安装、显示和 Rust 加速适配 | 业务规则、进程重启决策 | `host.py`, `display/`, `stdio.py`, `package.py`, `resource.py`, `rust.py`, `fsproxy.py` |
| `app/adapters/external/` | CookieCloud、插件市场、OCR、IP 归属和 MoviePilot Server 等命名外部生态 | 通用 HTTP/DNS/文件机制或可复用领域语义 | `market.py`, `server.py`, `cookiecloud.py`, `ocr.py`, `location.py`, `wechat.py` |
| `app/application/` | 聚焦应用服务、用例命令,以及由用例拥有的持久化/技术能力 Port/Protocol | SQLAlchemy、Session、Oper 等具体 DB 实现,具体 Adapter 静态依赖,多领域 Chain 编排、底层通用机制、通用传输协议 | `recognition.py`, `filter.py`, `outbox.py`, `subscription/write.py`, `workflow.py` |
| `app/application/messaging/` | 消息渲染/路由、交互和 Agent 到消息桥接:`ingress.py` 统一渠道回环入口;`interaction.py` 通用交互契约和视图工具`router.py` 统一交互优先级和回调分发;`site.py`/`subscribe.py`/`skill.py` 对应命令的会话、输入解析和视图;`media.py` 媒体交互状态(业务工作流仍由 `MediaInteractionChain` 执行);`plugin.py` 插件输入接管和插件按钮回调;`agent.py` Agent 选择状态、回调协议和 WebAgent 消息桥接;`message.py` 通知渲染、模板和队列。不作为推荐给插件直接使用的公开 SDK | 认证策略、通用 HTTP、服务发现、仅端点使用的 Web Push 行为 | `ingress.py`, `message.py`, `interaction.py`, `router.py`, `agent.py` |
| `app/application/` | 聚焦应用服务、用例命令,以及由用例拥有的持久化/技术能力 Port/Protocol;同一模块的多文件实现进入单词命名子目录 | SQLAlchemy、Session、Oper 等具体 DB 实现,具体 Adapter 静态依赖,多领域 Chain 编排、底层通用机制、通用传输协议 | `recognition.py`, `filter.py`, `outbox.py`, `subscription/write.py`, `workflow.py` |
| `app/application/messaging/` | 消息渲染/路由、交互和 Agent 到消息桥接:`ingress.py` 统一渠道回环入口;`interaction/` 承载通用状态和 Agent 选择契约;`channel/admin.py` 承载渠道管理员解析`router.py` 统一交互优先级和回调分发;`site.py`/`subscribe.py`/`skill.py` 对应命令的会话、输入解析和视图;`media.py` 媒体交互状态(业务工作流仍由 `MediaInteractionChain` 执行);`plugin.py` 插件输入接管和插件按钮回调;`webagent/` 承载 WebAgent 事件和流编排;`agent.py` 保留 WebAgent 应用编排。不作为推荐给插件直接使用的公开 SDK | 认证策略、通用 HTTP、服务发现、仅端点使用的 Web Push 行为 | `ingress.py`, `message.py`, `interaction/`, `channel/`, `webagent/`, `router.py`, `agent.py` |
| `app/application/security/` | 认证、授权、Cookie、Passkey、OTP/二次认证、路径/URL 安全、SSRF 和签名策略 | 通用 URL 解析、进程运行策略、普通业务校验 | `access.py`, `auth.py`, `cookie.py`, `passkey.py`, `otp.py`, `twofactor.py`, `url.py` |
| `app/chain/` | Reusable use-case orchestration across modules, Application services, injected ports, events, and caches; chains reach modules only through `run_module` dispatch on method-name contracts | Transport schemas, backend-specific protocol details, concrete Adapter imports, generic primitives, direct Oper/DB imports, direct imports of module internals (classes, exceptions, constants) | `media/`, `download/`, `subscribe/`, `transfer/` |
| `app/db/oper/` | 面向表和持久化值的 SQLAlchemy 数据访问;接收调用方 Session只查询、暂存或 flush | Application 业务规则、隐式事务所有权、外部副作用 | `subscribe.py`, `site.py`, `workflow.py` |

View File

@@ -54,6 +54,44 @@ from app.schemas.transfer import TransferInfo
from app.schemas.types import MediaSource
__all__ = [
"DownloadFileMutationRepository",
"DownloadFileSnapshot",
"DownloadFileWrite",
"DownloadHistory",
"DownloadHistoryMutationCommand",
"DownloadHistoryMutationRepository",
"DownloadHistoryQueryPort",
"DownloadHistoryRepository",
"DownloadHistorySnapshot",
"DownloadHistoryWrite",
"DownloadHistoryWritePort",
"HistoryMutationResult",
"HistoryQueryService",
"HistoryUnitOfWork",
"ManualTransferHistory",
"TransferHistory",
"TransferHistoryLookupRepository",
"TransferHistoryLookupService",
"TransferHistoryMonthlyStatistics",
"TransferHistoryMutationCommand",
"TransferHistoryPage",
"TransferHistoryQueryPort",
"TransferHistoryReplacePort",
"TransferHistoryRepository",
"TransferHistorySnapshot",
"TransferHistoryStagingPort",
"TransferHistoryStatisticSnapshot",
"TransferHistoryWrite",
"TransferHistoryWritePort",
"add_transfer_fail",
"add_transfer_success",
"configure_transfer_history_repository",
"get_transfer_history_repository",
"reset_transfer_history_repository",
]
@dataclass(frozen=True, slots=True)
class DownloadHistorySnapshot:
"""脱离数据库会话后供宿主下载、订阅和整理用例读取的历史快照。"""

View File

@@ -66,7 +66,7 @@ def build_web_agent_message_update_event(
"""构造可应用到 WebAgent 原消息的 SSE 更新事件。"""
button_rows = normalize_web_agent_button_rows(buttons)
content_parts = [part for part in (title, text) if part]
target_message = {
target_message: dict[str, Any] = {
"id": str(message_id),
"content": "" if button_rows else "\n\n".join(content_parts),
"choices": [],

View File

@@ -5,7 +5,7 @@
长在 SubscribeOper.add 上,但取标题、选海报尺寸、判音乐实体、决定哪几个字段构成一条
订阅的身份都是订阅业务的规则而非数据访问——Oper 只该收敛查询,领域对象不该出现在
它的入参里。搬上来之后 SubscribeOper 收到的是纯粹的持久化字典,与
app/application/history.py 里整理历史的写入路径同构。
app/application/history/ 里整理历史的写入路径同构。
留在 Oper 的是列类型强转与建库时间戳:那几步是为 PostgreSQL 的严格类型检查和订阅表
自己的列类型而存在的,跟着列走比跟着调用方走更不容易漂。

View File

@@ -29,7 +29,7 @@ from app.schemas.transfer import TransferJob, TransferJobTask
from app.schemas.types import MUSIC_ENTITY_ALBUM, MUSIC_ENTITY_RECORDING, MediaType
if TYPE_CHECKING:
from app.application.transfer.workflow import TransferTask
from app.application.transfer.models import TransferTask
def monotonic() -> float:
@@ -37,7 +37,7 @@ def monotonic() -> float:
workflow = sys.modules.get("app.application.transfer.workflow")
legacy_clock = getattr(workflow, "monotonic", None)
if callable(legacy_clock) and legacy_clock is not monotonic:
return legacy_clock()
return cast(float, legacy_clock())
return _system_monotonic()
JobId = tuple[object, ...]
@@ -176,7 +176,7 @@ class JobManager:
)
return fileitem.storage or "local", normalized_path
def __get_id(self, task: Optional[TransferTask] = None) -> JobId:
def __get_id(self, task: TransferTask) -> JobId:
"""
获取作业ID
"""

View File

@@ -12,7 +12,7 @@ from app.runtime.log import logger
from app.schemas.media import resolve_media_identity
if TYPE_CHECKING:
from app.application.transfer.workflow import TransferTask
from app.application.transfer.models import TransferTask
def build_transfer_failure_group_key(task: TransferTask) -> str:

View File

@@ -15,7 +15,7 @@ class _DictionarySerializable(Protocol):
class _TransferTaskMetaSource(Protocol):
"""描述整理任务提供已解析领域元数据的最小形状。"""
meta: object
meta: MetaBase | None
def domain_to_dict(value: object) -> dict[str, Any]:

View File

@@ -23,8 +23,6 @@ from typing import (
from app.application.transfer.jobs import (
DirectorySize,
JobManager,
_domain_to_dict,
_transfer_task_meta,
configure_directory_size,
job_lock,
)
@@ -52,14 +50,51 @@ from app.application.transfer.models import (
TransferTask,
)
from app.application.transfer.notifications import (
TransferFailureNotification,
TransferFailureNotificationAggregator,
build_transfer_failure_group_key,
)
from app.application.transfer.feedback import TransferFailureNotification
from app.application.transfer.projection import (
domain_to_dict as _domain_to_dict,
transfer_task_meta as _transfer_task_meta,
)
from app.schemas.file import FileItem
from app.schemas.transfer import TransferJob
__all__ = [
"DirectorySize",
"JobManager",
"configure_directory_size",
"job_lock",
"TRANSFER_ADMISSION_ACCEPTED",
"TRANSFER_ADMISSION_PLANNED",
"TRANSFER_ADMISSION_PROVIDER_PENDING",
"TRANSFER_PLAN_CHECKPOINT_LEGACY_VERSION",
"TRANSFER_PLAN_CHECKPOINT_VERSION",
"TRANSFER_PLANNING_INPUT_VERSION",
"TRANSFER_PROVIDER_INVOCATION_VERSION",
"TransferAdmission",
"TransferAdmissionConflictError",
"TransferAdmissionProjectionError",
"TransferAdmissionRepository",
"TransferCallback",
"TransferFailureNotification",
"TransferFailureNotificationAggregator",
"TransferLeaseLostError",
"TransferPlanCheckpoint",
"TransferPlanItem",
"TransferPlanningInput",
"TransferPlanningStateError",
"TransferProviderInvocationSnapshot",
"TransferProviderReference",
"TransferQueue",
"TransferTask",
"build_transfer_failure_group_key",
"TransferQueueService",
]
class TransferQueueService:
"""协调整理任务登记、入队、移除和队列视图查询。"""

View File

@@ -19,10 +19,7 @@ from app.application.agent import (
transcribe_audio,
)
from app.application.messaging import router as interaction_router
from app.application.messaging.interaction.agent import (
agent_interaction_manager,
parse_agent_choice_callback,
)
from app.application.messaging.interaction.agent import agent_interaction_manager, parse_agent_choice_callback
from app.application.messaging.interaction import InteractionContext, InteractionDispatch
from app.application.messaging.media import media_interaction_manager
from app.application.messaging.plugin import PluginInputInteractionHandler

View File

@@ -713,7 +713,7 @@ class TransferWorkflowOwner(_TransferOwnerBase):
raise OperationInterrupted()
file_path = Path(file_item.path)
# 自动整理按 app/application/history.py 的统一判定去重(失败记录放行重试、
# 自动整理按 app/application/history/ 的统一判定去重(失败记录放行重试、
# 成功但源文件已变化放行交 overwrite_mode 决断);手动整理可清理失败记录,
# 或按用户确认清理成功记录;手动显式指定媒体身份时,先解除旧失败任务再重新规划。
if (

View File

@@ -15,10 +15,11 @@ def condition_field_ids(node: ClassificationConditionNode) -> tuple[str, ...]:
return (node.field,)
if not isinstance(node, ClassificationConditionGroup):
return ()
children: tuple[ClassificationConditionNode, ...]
if node.all is not None:
children = node.all
children = tuple(node.all)
elif node.any is not None:
children = node.any
children = tuple(node.any)
elif node.not_ is not None:
children = (node.not_,)
else:

View File

@@ -128,7 +128,7 @@ class TransferDispatcher:
"""
依据整理历史判断本次是否跳过整理。
判定策略由 app/application/history.py 统一提供,整理链的计划整理段使用
判定策略由 app/application/history/ 统一提供,整理链的计划整理段使用
同一套判定,避免此处放行的文件在下游被另一套「存在记录即拦」的策略收回。
:param storage: 存储
:param src_path: 整理记录使用的源路径

View File

@@ -102,7 +102,7 @@ ARCH-201 至 ARCH-204 均达到实现、验证、提交、推送和远端门禁
| Event Contract | 53 | 均已有 payload model但当前全部是 diagnostic enforcement |
| Python 源码量 | 305,884 行 | 排除 `app/plugins/**`61 个文件超过 1,000 行11 个超过 2,000 行 |
| 长方法 | 290 个超过 80 行 | AST 统计排除 `app/plugins/**`65 个超过 150 行21 个超过 250 行 |
| 全量 mypy 历史债务 | 9,341 / 508 文件 | Agent API 重构后的现状基线canonical Facade 与 endpoint 类型边界已补齐,低水位只允许继续下降 |
| 全量 mypy 历史债务 | 9,329 / 507 文件 | Application 模块目录整理后的现状基线canonical Facade 与 endpoint 类型边界已补齐,低水位只允许继续下降 |
| Ruff 历史诊断 | 517 | 低水位门禁通过,但规则集只覆盖 `E4/E7/E9/F/I` |
| 覆盖率固定基线 | Application 80.00%Domain 80.00% | Chain、Runtime、Agent、Adapter、Startup 未进入包级覆盖率门禁 |

View File

@@ -60,22 +60,22 @@ to make the directory tree look symmetrical.
| Path | Ownership |
|---|---|
| `app/application/*.py` | Established single-module application services and compatibility facades |
| `app/application/*.py` | Established single-word application services; same-domain implementations use subpackages, while old paths are routed only by the exact Compat/SDK boundaries |
| `app/application/subscription/` | Subscription use cases: `write.py` owns media-to-row translation and the write port; `contract.py` owns shared metadata/media-key projection; query, mutation, deletion, identity and search stay in their single-word modules |
| `app/application/search/` | Search state and later search-plan use cases |
| `app/application/download/` | Download task querying/control and selection use cases; `failures.py` owns the frozen failure-cooldown write/query DTOs and persistence Port |
| `app/application/history.py` | History use cases and persistence contracts; DownloadHistory and TransferHistory own deeply frozen DTOs plus typed query/write/staging ports |
| `app/application/history/` | History use cases and persistence contracts; DownloadHistory and TransferHistory own deeply frozen DTOs plus typed query/write/staging ports |
| `app/application/music/` | Multi-source music catalog orchestration |
| `app/application/chain/` | Injectable Chain runtime capabilities: `context.py` owns the typed runtime and persistence dependency aggregate, and `events.py` owns durable event write contracts plus replayable payload conversion |
| `app/application/agent.py` | Agent orchestration facade and typed `AgentDataContext`; startup injects one explicit data context into the manager, memory, tool and scheduler owners without a process-wide persistence locator |
| `app/application/invocation.py` | Frozen Agent write-call identity, claim and receipt contracts; the injected repository provides atomic claim, fenced settlement and unresolved-state reads, while `db/adapters/invocation.py` owns short transactions and cold-start recovery is invoked by startup |
| `app/application/network.py` | System network-test target catalog, immutable public/private projections, URL and redirect admission, response validation and the injected transport Port; startup owns concrete HTTP Adapter assembly |
| `app/application/outbox.py` | Durable intent, transaction-only stager, short-transaction dispatch store, claim fencing and structured post-commit result contracts |
| `app/application/transfer/` | Durable transfer use cases: `workflow.py` owns admission/planning/queue behavior; `execution.py` owns stable operation identity, step/checkpoint state, retry/manual-review commands and terminal-settlement DTOs; `recovery.py` owns failed/corrupt task cleanup and history detachment through the execution repository; `history.py` projects history write fields and file fingerprints; `feedback.py` owns failure stages, notification snapshots and message text, while Chain owns notification delivery and cleanup side effects |
| `app/application/transfer/` | Durable transfer use cases: `workflow.py` owns queue service orchestration; `models.py` owns admission/planning/task contracts; `jobs.py` owns in-process task views; `notifications.py` owns failure aggregation; `projection.py` owns domain projections; `execution.py` owns stable operation identity, step/checkpoint state, retry/manual-review commands and terminal-settlement DTOs; `recovery.py` owns failed/corrupt task cleanup and history detachment through the execution repository; `history.py` projects history write fields and file fingerprints; `feedback.py` owns failure stages, notification snapshots and message text, while Chain owns notification delivery and cleanup side effects |
| `app/application/plugin/` | Plugin market catalog, installation command, installed-plugin identity contract and startup migration, runtime port, folder operations and dynamic-route use cases; filenames remain single words (`catalog.py`, `identity.py`, `migration.py`, `install.py`, `runtime.py`, `folders.py`, `routes.py`) |
| `app/application/server/` | MoviePilot Server reporting and sharing use cases; local data readers and transport callbacks are injected by startup |
| `app/application/site/` | Configured site catalog, authentication level and index-resource capability; the generated extension and its data bundle stay together here |
| `app/application/messaging/` | Message rendering/routing, interactions and the Agent-to-message bridge: `ingress.py` owns the single channel-to-host loopback boundary; `interaction.py` shared interaction contracts and view helpers; `router.py` unified interaction priority and callback dispatch; `site.py`/`subscribe.py`/`skill.py` per-command sessions, input parsing and views; `media.py` media interaction state while the business workflow stays in `MediaInteractionChain`; `plugin.py` plugin input capture and plugin button callbacks; `agent.py` owns Agent choice state, callback protocol, bounded WebAgent event publication, display projection, session identity/persistence coordination, temporary attachment registry and audio preparation/transcription; `message.py` notification rendering, templates and queue. Not a public SDK recommended for direct plugin use |
| `app/application/messaging/` | Message rendering/routing, interactions and the Agent-to-message bridge: `ingress.py` owns the single channel-to-host loopback boundary; `interaction/` owns generic interaction state plus Agent choice contracts; `channel/admin.py` owns channel administrator resolution; `router.py` unified interaction priority and callback dispatch; `site.py`/`subscribe.py`/`skill.py` per-command sessions, input parsing and views; `media.py` media interaction state while the business workflow stays in `MediaInteractionChain`; `plugin.py` plugin input capture and plugin button callbacks; `webagent/` owns WebAgent notification events and stream transport; `agent.py` owns WebAgent application orchestration, display projection, session identity/persistence coordination, temporary attachment registry and audio preparation/transcription; `message.py` notification rendering, templates and queue. Not a public SDK recommended for direct plugin use |
| `app/application/security/` | Authentication, authorization, frozen user/auth projections, atomic user aggregate commands, per-user configuration publication, cookies, passkeys, OTP/two-factor, path/URL safety, SSRF and signing policy |
### Agent runtime boundaries
@@ -122,10 +122,9 @@ directory categories.
`app/api/endpoints/agent.py` must not recreate WebAgent file registries, audio
conversion/transcription policy, traditional-message dispatch, Agent execution
lifecycle, event-to-display projection or AgentChat snapshot writes. Those reusable
state transitions and the transport-neutral event-stream use case belong to
`app/application/messaging/agent.py`; the endpoint maps FastAPI principals and DTOs,
translates upload/domain failures to HTTP responses, and frames Application events
as SSE.
state transitions belong to `app/application/messaging/agent.py` and its
`webagent/` subpackage; the endpoint maps FastAPI principals and DTOs, translates
upload/domain failures to HTTP responses, and frames Application events as SSE.
### Runtime boundaries
@@ -293,7 +292,7 @@ were host-internal migration scaffolding, never plugin ABI, and must not gain SD
Legacy public Agent imports remain exact SDK/Compat boundaries and must not be reintroduced as
Oper aliases in canonical Agent modules.
Monitor history checks use `get_transfer_history_repository()` from
`app/application/history.py`; old constructible Oper-style facades are available
`app/application/history/`; old constructible Oper-style facades are available
only through the exact SDK Legacy/Compat mapping.
Durable transfer execution follows one explicit boundary. The Chain freezes each
@@ -837,7 +836,7 @@ The configured user-configuration repository publishes its in-memory snapshot
only after the user transaction commits, and reloads from the database if
publication fails.
History is a verified typed boundary: `app/application/history.py` owns deeply
History is a verified typed boundary: `app/application/history/` owns deeply
frozen DownloadHistory and TransferHistory snapshots plus typed query/write and
staging ports. `app/db/adapters/history/download.py` and
`app/db/adapters/history/transfer.py` perform ORM projection and mutations inside
@@ -1110,7 +1109,7 @@ driven workflow registration.
| `app/application/download/failures.py` | Frozen download-failure cooldown write/query DTOs and Chain persistence Port |
| `app/db/adapters/download.py` | Short-session download-failure snapshot and mutation adapter |
| `app/db/adapters/mediaserver.py` | Per-operation media-server cache query/upsert/cleanup transaction adapter |
| `app/application/history.py` | History use cases; deeply frozen DownloadHistory/TransferHistory DTOs and typed query/write/staging ports |
| `app/application/history/` | History use cases; deeply frozen DownloadHistory/TransferHistory DTOs and typed query/write/staging ports |
| `app/db/adapters/history/download.py` | DownloadHistory short-session snapshot, query and mutation adapter |
| `app/chain/download/` | Stable DownloadChain facade plus single-owner selection, submission, batch, existence, failure, history, post-processing, subtitle, task and technical-port modules |
| `app/chain/search/` | Stable SearchChain facade plus shared execution, plan, provider, pagination, result, cache, title, media, music policy, subtitle, site and recommendation owners |
@@ -1122,7 +1121,7 @@ driven workflow registration.
| `app/application/outbox.py` | Durable intent, stager/store, claim fencing, topic handler and structured post-commit contracts |
| `app/db/adapters/outbox.py` | SQLAlchemy Outbox transaction-only stagers and short-transaction claim/settlement stores |
| `app/application/chain/events.py` | Chain durable-event write port, settlement projection and replayable payload conversion |
| `app/application/transfer/workflow.py` | Transfer task, durable admission, versioned planning input/checkpoint contracts and queue use case |
| `app/application/transfer/` | `models.py` owns transfer task, durable admission and versioned planning contracts; `jobs.py` owns task views; `workflow.py` owns the queue use case; execution, recovery, notification and projection policies remain in their single-word modules |
| `app/db/adapters/transfer/admission.py` | SQLAlchemy admission/checkpoint persistence, CAS state transition and detached snapshot adapter |
| `app/application/scheduling.py` | Runtime scheduler facade for Agent tools and endpoints; `Scheduler` class registered by `app/startup/initializers/scheduler.py` |
| `app/scheduler/` | Scheduler implementation package: stable facade plus catalog, execution/bridge/progress, registry, reconcile, lifecycle and maintenance owners; no business Chain construction |

View File

@@ -50,6 +50,30 @@ MYPY_PATH_MIGRATIONS = {
("app/agent/tools/impl/_plugin_tool_utils.py",),
("app/application/plugin/management.py",),
),
"history-package": (
(
"app/application/history.py",
"app/application/history_contracts.py",
"app/application/history_retry.py",
"app/application/historymutation.py",
),
("app/application/history/",),
),
"messaging-interaction-package": (
(
"app/application/messaging/interaction.py",
"app/application/messaging/agent_interaction.py",
),
("app/application/messaging/interaction/",),
),
"messaging-channel-package": (
("app/application/messaging/channel_admin.py",),
("app/application/messaging/channel/",),
),
"messaging-webagent-package": (
("app/application/messaging/webagentstream.py",),
("app/application/messaging/webagent/",),
),
}
# 形如 app/foo.py:12: error: 消息说明 [error-code];个别错误可能缺代码。

View File

@@ -8,7 +8,7 @@
"app/application/rss.py:RssHelper": 531,
"app/application/security/url.py:SecurityUtils": 771,
"app/application/torrent/download.py:TorrentHelper": 738,
"app/application/transfer/workflow.py:JobManager": 754,
"app/application/transfer/jobs.py:JobManager": 754,
"app/chain/_recognition.py:RecognitionMixin": 570,
"app/chain/base.py:ChainBase": 1161,
"app/chain/download/batch.py:DownloadBatchOwner": 515,
@@ -35,7 +35,6 @@
"file": {
"app/api/endpoints/system.py": 1152,
"app/application/formatting.py": 1523,
"app/application/history.py": 1348,
"app/application/messaging/agent.py": 2195,
"app/application/messaging/message.py": 1314,
"app/application/messaging/skill.py": 1300,

View File

@@ -634,7 +634,7 @@
"operator": 3,
"type-arg": 2
},
"app/application/history.py": {
"app/application/history/__init__.py": {
"no-any-return": 1
},
"app/application/image.py": {
@@ -652,22 +652,15 @@
"operator": 1
},
"app/application/messaging/agent.py": {
"arg-type": 1,
"attr-defined": 1,
"no-untyped-call": 1,
"no-untyped-def": 1
"arg-type": 1
},
"app/application/messaging/chat.py": {
"type-arg": 8
},
"app/application/messaging/interaction.py": {
"app/application/messaging/interaction/__init__.py": {
"no-untyped-def": 1,
"type-arg": 2
},
"app/application/messaging/media.py": {
"no-untyped-call": 1,
"no-untyped-def": 1
},
"app/application/messaging/message.py": {
"arg-type": 5,
"assignment": 9,
@@ -692,8 +685,7 @@
"no-untyped-def": 2
},
"app/application/messaging/skill.py": {
"no-untyped-call": 4,
"no-untyped-def": 4,
"no-untyped-def": 1,
"type-arg": 6
},
"app/application/messaging/subscribe.py": {

View File

@@ -1,7 +1,7 @@
"""
有界重试预算的端到端行为验证。
app/application/history.py 的查重闸真值表与计数器 API 已在
app/application/history/ 的查重闸真值表与计数器 API 已在
tests/test_transfer_history_gate.py 逐项覆盖,本文件换一个角度:把「同一源路径
连续多个监控事件」串成一条时间线,验证瞬时故障能在预算内自愈、耗尽预算后被拦、
以及删除整理记录会让预算重新满额,贴近真实使用场景。

View File

@@ -1,5 +1,5 @@
"""
覆盖 app/application/history.py 的整理历史查重闸。
覆盖 app/application/history/ 的整理历史查重闸。
监控分发app/monitor/dispatcher.py与整理链计划整理 ownerapp/chain/transfer/plan.py
共用这套判定,本文件只测判定本身的真值表与查询辅助函数,不涉及调用方。

View File

@@ -9,7 +9,7 @@
因此这里断言的是「落库后每个字段的实际值」,不是「调用了什么」。
它们与同一张表的读侧规则(查重闸,见 test_transfer_history_gate.py同住
app/application/history.py;此前长在 TransferHistoryOper 上,故本文件旧名为
app/application/history/;此前长在 TransferHistoryOper 上,故本文件旧名为
test_db_transferhistory_write_path.py。
"""
import pytest