fix(lint): resolve all 37 flake8 issues
CI / lint (pull_request) Failing after 14m13s
CI / test (pull_request) Has been skipped
CI / notify-on-failure (pull_request) Failing after 12m7s

- Remove 7 unused imports (F401)
- Fix 4 f-strings without placeholders (F541)
- Fix indentation and blank line issues (E127/E302/E402)
- Remove trailing whitespace on 22 blank lines (W293)

Pure formatting changes, no logic modifications.
This commit is contained in:
cfdaily
2026-06-11 08:55:05 +08:00
parent 7b788809d8
commit 2f1cb5c277
10 changed files with 67 additions and 46 deletions
+11 -5
View File
@@ -5,11 +5,13 @@
#
# 注意:只保留 pull_request 触发,避免 push + pull_request 双倍触发
#
# Gitea v1.23.4 限制注意
# - 不支持 failure() 表达式,用 always() + shell 条件判断替代
# - 不支持 concurrency / continue-on-error / timeout-minutes / permissions
# - 无内置 GITEA_TOKEN,需手动配置 PAT 为 secret
# - runs-on 只支持单个 label
# Gitea v1.26.2 已支持
# - concurrency groups#32751
# - 可配置 GITEA_TOKEN 权限(#36173
#
# 仍不支持:
# - failure() 表达式,用 always() + shell 条件判断替代
# - continue-on-error / timeout-minutes / permissions
name: CI
@@ -17,6 +19,10 @@ on:
pull_request:
types: [opened, synchronize]
concurrency:
group: ci-${{ gitea.ref }}
cancel-in-progress: true
jobs:
# ── Job 1: Lint ──────────────────────────────────────
lint:
+13 -4
View File
@@ -3,10 +3,15 @@
# 触发条件:
# - push 到 main 分支
#
# Gitea v1.23.4 限制注意
# - 不支持 failure() 表达式
# - 不支持 concurrency / permissions
# - 部署脚本 scripts/deploy.sh,支持 --version/--rollback/--health-check
# Gitea v1.26.2 已支持
# - concurrency groups#32751
# - 可配置 GITEA_TOKEN 权限(#36173
#
# 仍不支持:
# - failure() 表达式,用 always() + shell 条件判断替代
# - permissions
#
# 部署脚本 scripts/deploy.sh,支持 --version/--rollback/--health-check
name: Deploy
@@ -14,6 +19,10 @@ on:
push:
branches: [main]
concurrency:
group: deploy-${{ gitea.ref }}
cancel-in-progress: false
jobs:
# ── Job 1: CI(main 分支跑完整测试)─────────────────
ci:
+10 -3
View File
@@ -9,8 +9,12 @@
# Agent spawn 走生产 openclaw(全局单例,无法隔离),
# 测试 case 用 UUID 前缀标识。
#
# Gitea v1.23.4 限制注意
# - 不支持 workflow_run 触发器(无法直接 needs 另一个 workflow 的 job
# Gitea v1.26.2 已支持
# - concurrency groups
# - workflow_dispatch 触发器(已支持)
#
# 仍不支持:
# - workflow_run 触发器(无法直接 needs 另一个 workflow 的 job
# - 此 workflow 需手动触发或在 deploy.yml 中以 needs 方式调用
# - 实际使用时可能需要合并到 deploy.yml 作为同一个 workflow 的 job
# - 或依赖 daemon Webhook 监听 deploy 完成事件后通过 API 触发
@@ -19,13 +23,16 @@ name: E2E Tests
on:
workflow_dispatch:
# 手动触发,可选参数
inputs:
test_filter:
description: 'Test filter (e.g. tests/e2e/test_api.py)'
required: false
default: 'tests/e2e/'
concurrency:
group: e2e-${{ gitea.ref }}
cancel-in-progress: true
jobs:
e2e:
runs-on: ubuntu-latest
+21 -21
View File
@@ -10,7 +10,7 @@ from dataclasses import dataclass
from pathlib import Path
from typing import Optional
from src.daemon.prompt_composer import PromptContext, PromptComposer, PromptSection
from src.daemon.prompt_composer import PromptContext, PromptSection
from src.blackboard.db import get_connection
logger = logging.getLogger("moziplus-v2.handler")
@@ -28,46 +28,46 @@ class VerifyResult:
class BaseTaskHandler:
"""所有 task type handler 的基类。
职责:L2 引擎注入层的业务逻辑——prompt 构建、完成验证、状态标记。
不管:进程生命周期、exit 分类、重试决策(这些归 spawner)。
"""
# crash 类 outcome(进程级异常,需要 rollback)
CRASH_OUTCOMES = frozenset({
"crashed", "compact_failed", "process_crash",
"session_stuck", "compact_hanging",
})
task_type: str = ""
virtual_project: Optional[str] = None
display_name: str = "" # 中文展示名(ticker 扫描日志用)
# === 子类必须实现 ===
def build_prompt(self, context: PromptContext) -> str:
"""构建 L2 prompt(通过 PromptComposer 拼 section)。子类实现。"""
raise NotImplementedError
def verify_completion(self, task_id: str, db_path: Path) -> VerifyResult:
"""验证任务完成质量。每个 handler 自己的验证逻辑。子类实现。"""
raise NotImplementedError
def target_success_status(self) -> str:
"""验证通过后的目标状态。task='review', mail/toolchain='done'"""
return "review"
def get_sections(self) -> list[PromptSection]:
"""返回此 handler 的 prompt section 列表。子类实现。"""
return []
# === 基类提供统一流程 ===
def pre_spawn(self, task_id: str, db_path: Path) -> bool:
"""spawn 前业务准备。默认 True。
mail/toolchain override 为 auto_working。"""
return True
def post_complete(self, task_id: str, agent_id: str,
outcome: str, db_path: Path) -> None:
"""spawn 完成后的业务处理。统一 4 步流程:
@@ -80,10 +80,10 @@ class BaseTaskHandler:
if outcome in self.CRASH_OUTCOMES:
self._rollback_current_agent(db_path, task_id, agent_id)
return
# 2. verify
result = self.verify_completion(task_id, db_path)
# 3. mark
if result.passed:
self._mark_task_status(db_path, task_id, self.target_success_status())
@@ -92,20 +92,20 @@ class BaseTaskHandler:
else:
# 4. notify
self.on_failure(task_id, agent_id, db_path, result)
def on_failure(self, task_id: str, agent_id: str,
db_path: Path, verify: VerifyResult) -> None:
"""验证失败处理。默认:标 failed。子类可 override。"""
self._mark_task_status(db_path, task_id, "failed")
logger.info("Task %s: verify failed (%s), marked failed",
task_id, verify.reason)
task_id, verify.reason)
def check_completion(self, task_id: str, db_path: Path) -> bool:
"""ticker 级别的完成检查。默认:False。"""
return False
# === 内部工具方法 ===
def _rollback_current_agent(self, db_path: Path, task_id: str, agent_id: str) -> None:
"""crash 后回退 current_agent → assignee,避免 exclude_current 卡死。
从 dispatcher._rollback_current_agent 迁移。"""
@@ -126,7 +126,7 @@ class BaseTaskHandler:
except Exception as e:
logger.warning("Task %s: failed to rollback current_agent: %s",
task_id, e)
def _mark_task_status(self, db_path: Path, task_id: str, status: str) -> None:
"""更新任务状态 + 写审计事件(带 3 次重试,防 SQLite DB 锁)。"""
for attempt in range(3):
@@ -157,7 +157,7 @@ class BaseTaskHandler:
logger.warning("Handler: mark %s%s attempt %d failed: %s",
task_id, status, attempt + 1, e)
logger.error("Handler: mark %s%s all 3 attempts failed", task_id, status)
def _auto_mark_working(self, task_id: str, db_path: Path) -> bool:
"""pending → workingmail/toolchain 通用)。"""
try:
+3 -3
View File
@@ -7,7 +7,6 @@ from __future__ import annotations
import json
import logging
from pathlib import Path
from typing import Dict, Optional
from src.daemon.base_task_handler import BaseTaskHandler, VerifyResult
from src.daemon.prompt_composer import PromptComposer, PromptContext
@@ -15,6 +14,7 @@ from src.blackboard.db import get_connection
logger = logging.getLogger("moziplus-v2.handler.mail")
class MailHandler(BaseTaskHandler):
"""Mail 任务 handler。"""
@@ -65,7 +65,7 @@ class MailHandler(BaseTaskHandler):
"""request 验证失败 → 标 failed + 通知发件人"""
self._mark_task_status(db_path, task_id, "failed")
logger.info("Mail %s: request verify failed (%s), marked failed",
task_id, verify.reason)
task_id, verify.reason)
# 通知发件人
try:
@@ -95,7 +95,7 @@ class MailHandler(BaseTaskHandler):
def _check_reply(self, task_id: str, db_path: Path) -> bool:
"""检查是否已回复(查 tasks 表找 in_reply_to 回复邮件)
从 dispatcher._mail_check_reply 迁移。
Mail 回复机制:创建新 taskmust_haves JSON 中包含 in_reply_to = original_task_id。
不能查 comments 表——回复邮件是独立的 task,不是 comment。
+1 -1
View File
@@ -6,7 +6,7 @@ prompt_composer.py — PromptSection Protocol + PromptContext + PromptComposer
import logging
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Protocol, runtime_checkable
from typing import Dict, List, Optional, Protocol, runtime_checkable
logger = logging.getLogger("moziplus-v2.prompt_composer")
+1 -2
View File
@@ -16,11 +16,10 @@ from pathlib import Path
from typing import Any, Dict, List, Optional
from src.blackboard.db import get_connection
from src.daemon.task_type_registry import TaskTypeRegistry
logger = logging.getLogger("moziplus-v2.spawner")
from src.daemon.task_type_registry import TaskTypeRegistry
# ── Prompt 模板 ──
+3 -3
View File
@@ -7,7 +7,7 @@ from __future__ import annotations
import logging
import os
from pathlib import Path
from typing import Dict, List, Optional
from typing import Dict, Optional
from src.daemon.base_task_handler import BaseTaskHandler, VerifyResult
from src.daemon.prompt_composer import PromptComposer, PromptContext
@@ -182,7 +182,7 @@ class TaskConstraintsSection:
class TaskHandler(BaseTaskHandler):
"""黑板标准任务 handler。
- verify: 三信号检查(output / comment / terminal status
- 成功 → review
- 失败 → 保持 working,让 ticker 重试
@@ -198,7 +198,7 @@ class TaskHandler(BaseTaskHandler):
def post_complete(self, task_id: str, agent_id: str,
outcome: str, db_path: Path) -> None:
"""Task on_complete:区分 executor 和 review。
executor: 基类统一流程(crash → verify → mark review
review: handle_review_complete(读 verdict → done/keep review
"""
+1 -1
View File
@@ -9,7 +9,7 @@ from __future__ import annotations
import logging
from pathlib import Path
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Protocol, runtime_checkable
from typing import TYPE_CHECKING, Dict, Optional, Protocol, runtime_checkable
if TYPE_CHECKING:
from src.daemon.prompt_composer import PromptContext
+3 -3
View File
@@ -38,13 +38,13 @@ class ToolchainContextSection:
return render_template(event_type, variables)
# fallback:通用事件描述
lines = [f"## 工具链事件", f""]
lines = ["## 工具链事件", ""]
lines.append(f"- **事件类型**: {event_type or '未知'}")
if event_data:
lines.append(f"- **事件详情**:")
lines.append("- **事件详情**:")
for key, value in event_data.items():
lines.append(f" - {key}: {value}")
lines.append(f"")
lines.append("")
return "\n".join(lines)
def should_include(self, context: PromptContext) -> bool: