update # 初始化仓库

This commit is contained in:
2026-10-15 14:14:58 +08:00
commit ff03600ae9
859 changed files with 17559 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
# 长期规划
## 已确认目标
一个 farm 主仓库统一开发农场逻辑;面向真寻、普通 NoneBot 和
AstrBot 生成不同插件;三个发布仓库只承载各自的安装内容。
用户不需要下载其他框架的接入代码。
保留旧项目功能作为需求调查基础,不默认旧实现正确,也不默认旧
README 中所有功能都要无条件保留。先修数据一致性,再增加玩法。
## 建议的首个版本范围
保留开通农场、查看、种子商店、购买、播种、收获、铲除、出售、
锁定、土地升级、签到、偷菜、改名。逐项核对旧指令与返回行为。
真寻金币兑换为真寻专有可选能力;其他框架不凭空生成外部金币。
点券、远程签到与星级规则在决策确认后进入规格。
首版不做交易行、钓鱼、跨实例在线联机、账号自动绑定、Web 后台、
通用插件引擎、复杂事件总线和微服务。后续依据需求增加。
## 里程碑和退出条件
| 阶段 | 工作 | 完成标准 |
|---|---|---|
| M0 初始化 | 代码保全、审查、设计和忽略规则 | 哈希可验证;实现与计划状态清楚 |
| M1 规格收敛 | 确定身份、共享范围、经济与迁移策略 | 决策表关键项已确认,行为示例可验收 |
| M2 核心与存储 | 注册、货币、库存、迁移及事务 | 无框架依赖;失败回滚、重试幂等、并发余额测试通过 |
| M3 种植闭环 | 购买→播种→收获→出售、土地升级 | 边界、星级、锁定、经验计算及时间测试通过 |
| M4 真寻接入 | 保留既有用户入口,迁移旧数据 | 真实宿主的安装、启停、文本/图片与恢复演练通过 |
| M5 其他接入 | 普通 NoneBot、AstrBot | 每个宿主独立安装;无其他框架依赖;功能矩阵通过 |
| M6 发布链路 | 分包、来源清单、发布仓库同步 | ZIP/wheel 安装测试、凭据与体积检查、可重试发布通过 |
| M7 稳定运营 | 性能、备份、资源供应与升级 | 有容量指标、兼容矩阵和版本回滚演练 |
| M8 可选联机 | 独立服务、账号映射、共享状态 | 另立需求,不直接共用多个进程的 SQLite 文件 |
阶段顺序表达依赖,不作未经验证的工期承诺。M4/M5 先打通一个最小
指令与完整交易闭环,再扩展全部指令;不要先写完所有框架外壳。
## 质量门槛
- 新玩法先给数值和边界例子;保留用户接受的契约。
- 每次修改聚焦一个可验收用例,避免同时换数据库、框架和玩法。
- 测试以交易不变量、并发、迁移和真实安装为主,不只检查函数返回。
- 核心测试不能依赖机器人、外网或图片渲染器。
- 每次发布追溯到主仓库提交、目标、资源版本、schema 和依赖清单。
- 所有目标达到对应门槛才能称为“支持”;未实现目标保持禁用。
+110
View File
@@ -0,0 +1,110 @@
# 代码设计与目录
## 原则与当前状态
下列为建议设计,尚未实现。当前旧代码位于 legacy,未把其全局变量、
数据库管理器和服务定位器直接当作新核心继续复用。
采用一个共享 Python 包,内部按职责划分,避免先建多个互相依赖的
独立发行包。共享源码只维护一份;发布时复制进各插件私有目录。
## 目标结构
```text
farm/
src/farm_core/
domain/ # 规则、值对象、状态转换,不做 I/O
application/ # 注册/购买/播种等用例,拥有事务边界
ports/ # 必要的仓储事务、时钟、外部钱包契约
infrastructure/
sqlite/ # 连接、仓储、schema migration
resources/ # 作物目录、资源校验与更新
presentation/ # 框架无关展示数据;可选图片渲染
integrations/
zhenxun/ # 真寻命令、配置、金币、数据目录、生命周期
nonebot/ # 普通 NoneBot 插件,不导入真寻
astrbot/ # AstrBot 插件,不导入 NoneBot 或真寻
assets/ # 经整理、版本化的资源,尚未从 legacy 提取
tests/
unit/ integration/ contracts/ migrations/ packaging/
release/ # 构建目标、文件白名单、依赖与模板
scripts/ # 离线校验、迁移、未来打包工具
legacy/ # 旧实现参考;不进入新插件安装包
docs/
```
本轮只创建职责说明及迁移基线,不生成大量空模块或假实现。
当一个用例实施时,才创建所需模块。
## 依赖方向
```mermaid
flowchart TD
Z[真寻接入] --> A[应用用例]
N[NoneBot 接入] --> A
B[AstrBot 接入] --> A
A --> D[领域规则]
A --> P[必要接口]
S[SQLite 实现] --> P
R[资源实现] --> P
Z --> C[组装与生命周期]
N --> C
B --> C
C --> S
C --> R
A --> V[展示数据]
V --> I[可选图片渲染]
```
基础设施实现接口,由宿主启动阶段组装并注入;领域与应用代码不能
访问框架全局对象、事件、配置管理器或消息发送 API。
记录日志使用标准 logging,接入层按需桥接宿主日志。
## 每层的责任
| 层 | 应做 | 禁止混入 |
|---|---|---|
| 命令接入 | 参数解析、用户上下文、权限、确认、发送回复 | 再写一套价格/奖励计算 |
| 应用用例 | 业务校验、幂等、事务、调用领域计算 | 对聊天平台对象直接操作 |
| 领域规则 | 土地/星级/经验计算与状态转换 | SQL、网络、图片、框架导入 |
| 存储 | 条件更新、查询、schema 升级 | 命令文案、签到奖励选择、图片 |
| 展示 | 将结果渲染为文本/图片 | 修改余额和农场状态 |
| 资源 | 校验、版本、缓存与原子切换 | 未验证即覆盖线上目录 |
命令与业务服务返回明确结果,例如成功、余额不足、种子不足、
已处理、状态冲突;结果包含展示所需数值和错误码。
数据库故障不能转换成“没有记录”或“没有农场”。
## 最小接口建议
- UnitOfWork:一次用例获取同一事务下的仓储;成功才提交。
- Clock:提供带时区的当前时间,使跨日、成熟和签到可测试。
- PlantCatalog:提供带版本的作物定义,已种植实例绑定规则版本。
- ExternalWallet:仅在真寻金币等外部经济接入时启用,明确幂等与补偿。
不要为字符串工具、日志和每个函数都建接口。
领域对象使用明确数据类型,取代任意 dict[Any, Any]。
注册、库存、地块、货币、收获周期分别建模,枚举及字段有说明。
## 生命周期和异步模型
导入模块时不启动清理线程、不连接数据库、不发送网络请求。
宿主启动:验证配置→迁移→初始化仓储/资源→就绪;
宿主停止:拒绝新写入→等待在途用例→关闭连接和任务。
首期建议单进程嵌入式部署。不要用 threading.RLock 代替异步业务锁。
事务连接生命周期由 UnitOfWork 管理;即使使用进程内锁,SQL 仍需
条件更新和唯一约束。查询缓存首期可不做;需要时在提交后失效,
不缓存不存在的用户作为有效玩家,不把缓存余额作为扣款依据。
## 发布时的包隔离
src/farm_core 内部一律采用相对导入。
构建时复制为 <插件包>/_vendor/farm_core,接入层经包内路径导入。
_vendor 必须是普通包且顶层初始化无副作用。
禁止把共享核心作为全局同名 farm_core 安装后又在插件中带另一份,
避免同时安装真寻/NoneBot 包时导入碰撞。
第三方依赖只列核心必需项和当前接入层项;渲染依赖可选。
私有命名空间能隔离源码名称,不能隔离同一 Python 进程的第三方依赖
版本;冲突必须通过兼容测试或分进程解决。
+101
View File
@@ -0,0 +1,101 @@
# 业务逻辑与一致性设计
状态:以下是建议约束。涉及用户资产归属、玩法与跨实例互通的选择,
需按 07-decisions.md 确认后进入正式规格。
## 身份与农场归属
框架(真寻/NoneBot/AstrBot)不等于消息平台(QQ/Telegram 等)。
玩家至少需要 deployment_id、realm_id、platform、platform_user_id;
platform_user_id 保存字符串,禁止跨平台按相同数字自动认定同一人。
建议独立部署默认独立数据,realm 可配置群内或部署内共享。
各协议暴露的同平台 ID 也未必同义,官方 QQ 的开放标识与 OneBot
账号不能自动合并。迁移需要明确来源命名空间、人工确认映射与审计。
双人操作如偷菜必须确定双方处于同一允许交互的 realm,
检查自己偷自己、跨群目标、无农场目标和权限。@对象解析留在接入层。
## 货币与库存
- 内部货币、数量使用整数;设置合理上限并检查乘法后的范围。
- 增量和设置新值采用不同接口名称;应用层不能直接写余额缓存。
- 扣款使用数据库条件更新,例如余额足够才扣减,检查实际影响行数。
- 不足返回明确失败;不能静默把负余额截成零后继续发货。
- 每次资产变动记录 operation_id、actor、realm、币种、增量、原因、
关联物品和提交时间;日志不代替可查询的账本。
- 已锁定作物在单项出售、批量出售、交易与其他消耗入口采用一致规则。
- 所有数量入口测试 0、负数、缺省、超大值、全部数量与库存不足;
命令层的默认参数不得被误当成任意合法业务值。
## 购买与出售
购买:读取有效目录→校验数量/等级→同一事务中校验和扣款→增加种子
→写操作流水→提交→生成展示数据。任一步失败整体回滚。
出售:按明确数量计算可出售库存→同一事务中检查锁定和库存版本
→扣库存→只增加本次收益→流水→提交。返回实际成交数量与新余额。
网络发送失败不回滚已成交交易;重试同一 operation_id 返回原结果。
## 播种与收获
播种:空地校验、种子消耗、星级选择、作物实例创建在同一事务中。
土地收益与生长速度采用已确认公式,记录规则或目录版本,
不能让资源更新悄悄改变已播种作物的结算契约。
收获:每块地独立计算产量和经验,再求和;不对累计经验反复加成。
每轮作物有可辨识的 cycle_id/harvest_index,防止重试和并发重复领奖。
作物入仓、经验增加、收获次数、下一成熟时间或枯萎状态、偷取记录
的结算必须在同一业务事务内完成。精确的事务批次由全收获与部分成功
策略决定,先定义用户可见结果,不能任意留半完成状态。
未种植、生长中、成熟、枯萎是明确状态;不要用多组互相冲突的布尔值
表示同一阶段。除草、虫害、施肥等独立属性另行建模。
## 签到、升级与确认
签到采用明确业务时区,(realm、player、business_date) 唯一;
签到记录、奖励发放、累计奖励领取标记在同一事务内。
“已签到”与“新签到成功”分开返回,防止重复展示发奖。
补签与连续签到规则分别定义,不从字段名猜测。
开垦和土地升级在用户确认后重新读取余额与地块状态,重新校验条件。
确认凭据绑定发起人、会话、动作、参数、过期时间和一次性标识;
不能把任何消息里的“是”当作任意待办操作的确认。
升级使作物成熟这一旧行为需明确保留或调整。
## 幂等与并发
operation_id 由框架事件标识与部署作用域产生;没有稳定事件标识时,
用已持久化的交互操作标识,而不是每次重试生成新的随机 ID。
同一操作不同参数应拒绝,不能错误复用第一次结果。
唯一约束、条件更新或状态版本是最终防线。
进程内锁只作辅助,跨进程不能共享这把锁。
单实例 SQLite 的连接/事务应由一个明确管理者协调;
BEGIN 的锁等待、busy timeout、取消回滚、事务嵌套和连接关闭都要测试。
WAL 是部署选项,不能解决错误的业务事务边界。
## 外部金币兑换
真寻金币和本地农场币位于不同存储,不能承诺一个本地 SQLite 事务
同时回滚两边。先核对外部钱包是否支持 operation_id、条件扣款、
查询和退款;使用持久化兑换单与可重试状态机协调。
无法确认结果时进入待对账状态,禁止直接重复扣款或盲目发币。
普通 NoneBot、AstrBot 默认只支持内部农场货币;
外部经济系统通过能力配置接入,不导入真寻代码。
兑换比例、手续费、舍入、最小单位和失败恢复写入明确规格。
## 时间、事件与展示
保存 UTC 时间戳,业务日期按配置时区计算;日志记录时区语义。
时钟可注入,覆盖午夜、闰日、月切换和重启后的结算。
核心状态改变必须由事务内显式步骤完成。
提交后的消息、图片、统计等副作用失败不撤销已提交业务;
需要可靠重试时使用操作结果或持久化任务。事件槽捕获异常不能把
必需的资产更新失败隐藏成成功。首期不必新增通用事件总线。
展示读取业务结果,不在绘图过程中更新余额或土地;
图片失败回退文本,不重复执行业务。
+101
View File
@@ -0,0 +1,101 @@
# 一个主仓库与多个发布仓库
## 已确认的仓库关系
| 角色 | 远程地址 | 建议职责 |
|---|---|---|
| 开发主仓库 | 尚未提供;本地 D:/Work/farm | 业务、接入、测试、文档、构建的唯一开发源 |
| 真寻发布仓库 | https://github.com/Shu-Ying/zhenxun_plugin_farm.git | 真寻完整插件 |
| AstrBot 发布仓库 | https://github.com/Shu-Ying/astrbot_plugin_farm.git | AstrBot 完整插件 |
| NoneBot 发布仓库 | https://github.com/Shu-Ying/nonebot_plugin_farm.git | NoneBot 包及 PyPI 构建资料 |
三个发布仓库已存在,不是空仓库,也不是 Git 子模块。
本轮曾按用户要求完成 clone,随后用户要求停止并删除,三个本地副本
及 .release-workspaces 已删除。不再 clone/fetch/pull/push。
历史分支和提交记录保留在 repository-inventory.json,并标明已删除。
历史观察:三个远程默认分支均为 main;与源 Beta 的代码布局不同。
因此未来不能直接覆盖 main 或假设旧 Beta 就等于远程稳定版。
首次接管发布流程必须先核对各仓库现有功能、许可、兼容性和用户安装路径。
## 发布内容与目录
每个发布产物 = 同一主提交的共享核心 + 当前框架接入 + 对应依赖
+ 必需资源 + 许可证/归属 + 来源清单。
legacy、docs、tests、开发工具、其他框架入口、真实数据不进入安装包。
真寻仓库根保留其可被插件目录直接加载的布局;AstrBot 根保留
main.py、metadata.yaml、配置描述和 requirements.txt 等宿主所需文件;
NoneBot 根为 pyproject.toml 加 nonebot_plugin_farm/ 模块。
这些布局必须以真实宿主安装验证为准,不只检查文件名。
各插件私有包含 _vendor/farm_core;共享核心内部使用相对导入。
NoneBot wheel 明确包含资源;不能假设 zip 的相对目录在 wheel 内
也自动存在。分别验证仓库安装、ZIP 安装和 wheel 安装。
## 建议发布流程
1. 选定主仓库提交或受保护版本标签,计算统一版本和资源版本。
2. 对各目标执行文件白名单组装,不从开发目录无差别复制。
3. 运行核心测试、迁移、依赖边界检查及对应宿主加载/启停测试。
4. 生成 ZIP/wheel、SHA-256、文件清单、构建环境与来源信息。
5. 校验资源大小、许可证、无其他框架代码/依赖、无令牌和玩家数据。
6. 为每个发布仓库生成可审查的候选差异;首次切换先 PR,
经授权后发布。PR/推送/发布不由这份设计文档自动授权。
7. 在发布仓库内用普通提交更新产物,不 force push,不改写历史。
8. 提交安装内容和来源清单后,再创建指向同一提交的发布标签。
9. 按目标发布到仓库/Release/PyPI,并记录各目标结果。
未来可使用 GitHub Actions;本轮未编写可执行发布工作流、未配置凭据。
发布工作区使用隔离的临时目录;清理只允许精确列出的生成路径。
保留目标仓库中的治理资料和人工维护文件,禁止无条件清空仓库。
## 版本、重试与回滚
首期建议核心和插件采用统一产品版本;目标元数据附 source_commit、
target、resource_version、schema_version 和构建内容哈希。
来源清单不能嵌入“包含清单本身的整个包哈希”形成循环依赖;
先列内容哈希,最终包哈希写独立校验附件。
跨仓库更新不是一个 Git 事务。为一次发布保存发布 ID 和目标状态;
部分失败只重试相同来源的失败目标,不重新构建不同内容冒充同版本。
相同来源、版本和目标应生成相同文件内容;统一归档排序及时间元数据。
已有标签和已上传 PyPI 版本不可覆盖,用新修复版本处理。
回滚插件二进制/源码不代表可以回滚数据库。
只有 schema 向后兼容或恢复备份后才能回退;停止机器人并校验后操作。
禁止用户通过退回旧包直接打开不兼容的新数据库。
## 权限与触发
GITHUB_TOKEN 限于当前仓库场景,跨仓库同步需另设明确授权;
建议使用仅获三个目标仓库权限的 GitHub App 安装令牌。
不在配置文件内写 PAT、不把令牌放 Git URL,不在不可信 PR 中执行发布。
构建可读权限与发布写权限分开,发布使用受保护环境和固定目标白名单。
凭据由仓库 Secrets/环境提供,版本和目标必须校验。
## 资源体积与分发
本轮测得迁移基线 ZIP 为 26,084,694 字节,约 24.9 MiB;
这是尺寸探测,不是可安装发布包。
AstrBot 当前发布文档列出的市场 ZIP 上限为 16 MB,因此直接打包全量
旧资源不可行。优先审查未使用图片、无损优化和基础资源集;
如仍需外置资源,采用固定版本、HTTPS、哈希和大小上限、
临时下载验证后原子安装,提供离线资源包。
不默认开发版直连远程服务,不跟随 latest 获取未绑定版本的作物库。
必须决定首次离线可玩范围、远程资源不可用时的回退、资源包保留版本,
以及图片和字体的分发权属。资源 schema 也要跟随代码兼容矩阵。
## 官方依据
核对日期:2026-10-15;正式发布前重新验证。
- [AstrBot 发布说明](https://docs.astrbot.app/dev/star/plugin-publish.html):
仓库元数据与市场 ZIP 体积要求。
- [AstrBot 安装方式](https://docs.astrbot.app/use/plugin.html):
仓库链接或 ZIP 文件安装。
- [NoneBot 发布说明](https://nonebot.dev/docs/developer/plugin-publishing):
Python 包、PyPI 与官方商店发布路径。
- [GitHub Actions 身份验证](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token):
GITHUB_TOKEN 权限与其他授权方式。
+61
View File
@@ -0,0 +1,61 @@
# 旧代码与数据迁移
## 本轮实际同步
源:D:/Work/zhenxun_plugin_farm,Beta 分支,
提交 b015c6c1997f146f651b677382980d338a306bb2。
复制工作区中受版本管理的文件,不复制 .git、未跟踪的工具安装目录。
源 .gitignore 含上轮 Comet 规则,未复制;新主仓库使用自己的忽略策略。
目的地:legacy/zhenxun_plugin_farm。827 个文件、35 个 Python 文件、
静态配置、HTML、图片以及两个仅含 plant/sqlite_sequence 表的作物库。
两库只读 quick_check 均为 ok,未复制运行中的 farm.db 或玩家备份。
静态资源是否全有合法分发授权尚未确认。
唯一源码差异:utils/request.py 的硬编码服务令牌改为读取
FARM_SERVICE_TOKEN,未把原值复制到新仓库。
来源哈希、复制哈希及差异说明见 legacy-manifest.json。
原项目未修改,服务端令牌轮换需另行处理。
## 旧模块复用地图
| 旧位置 | 新去向 | 迁移方式 |
|---|---|---|
| command.py、根 __init__.py | integrations/zhenxun | 保留用户指令契约,重写生命周期和参数适配 |
| core/farm.py、core/shop.py | application、domain | 按用例提取,先修计算和交易缺陷 |
| core/database | infrastructure/sqlite | 明确 schema 与事务所有权,不直接照搬 |
| core/player | 领域模型/查询模型 | 首期移除余额权威缓存,不移植后台线程池 |
| utils/darw、HTML | presentation/资源 | 去除真寻 BuildImage 依赖,支持文本降级 |
| utils/request、utils/json | resources | 配置校验、版本固定、下载原子性 |
| event | 提交后副作用 | 逐个核对必要用途,不先移植通用信号层 |
| core/activity/activity.py、effect.py | 后续玩法候选 | 隔离加载失败,不接入首版 |
| resource/db | 版本化作物目录 | 区分内置只读目录与可写玩家数据库 |
## 真实用户数据迁移建议
当前没有读写任何真实玩家库,以下尚未实施:
1. 盘点实际部署版本、schema、来源平台、玩家数量和货币含义。
2. 停写并备份,记录 schema、文件哈希和备份位置;备份不入 Git。
3. 使用副本进行只读预检:主键、重复、负数、孤儿地块、未知作物、
作物成熟时间、锁定、签到日期、币种和数值范围。
4. 明确旧裸 UID 到新身份命名空间的映射,不自动跨平台合并。
5. 版本化迁移脚本写入新数据库,保存 migration_id 和 schema_version。
6. 校验用户数、各币种合计、种子/作物数量、地块数及抽样业务状态,
对每一项转换或舍弃生成报告;再次执行不得重复导入。
7. 在目标框架演练最小玩法闭环、时区与资源加载,再切换数据目录。
8. 若失败,停写后恢复旧程序与原备份,不让两个版本并行写同一数据库。
旧代码存在余额和经验重复增加,无法仅凭当前余额还原“正确历史值”。
是否保留已有资产、重置、补偿或人工对账必须由用户明确决定,
不在迁移脚本中暗自纠正或清零。
## 首次发布仓库接管
当前本地 Beta 基线不等于三个发布仓库 main。
未来需要取得重新拉取授权后,对比现有功能和依赖,记录有价值的框架
接入代码与差异,再决定复用方式。不能本轮默认把远程现有代码覆盖成
Beta,也不能把已有 AstrBot/NoneBot 实现宣称已经合并进新主仓库。
发布仓库地址已纳入设计,检出已按用户要求删除。仅迁移基线保留在
主仓库,主仓库没有 Git 子模块和发布仓库副本。
+62
View File
@@ -0,0 +1,62 @@
# 源码审查
日期:2026-10-15。范围:旧 Beta 迁移基线的关键用例、数据层、
玩家缓存、初始化、资源请求和未完成的活动模块。
结论:有功能拆分基础,但交易边界、状态权威、错误传播和分层不足,
不建议直接在此结构上继续扩展跨框架玩法。
## 证据与限制
代码图提供符号和调用线索,覆盖检查报告 metadata_changed;
以下结论均回到源码核对,不以图的缺边证明代码不存在。
链接指向复制基线,通常与源行号一致;request.py 已移除令牌。
本轮语法检查和两个模块隔离加载见 baseline-checks.json。
没有启动真实宿主、执行完整插件导入、联网访问旧服务或开展并发压测。
P1:数据、资产或主要功能错误,应在新核心实施前处理。
P2:功能契约或维护可靠性问题。风险项与已证实缺陷分别标识。
## 已确认缺陷
| 编号 | 等级 | 证据 | 触发与影响 | 修复方向 |
|---|---|---|---|---|
| F01 | P1 | [shop.py:241](../legacy/zhenxun_plugin_farm/core/shop.py#L241)、[player.py:62](../legacy/zhenxun_plugin_farm/core/player/player.py#L62) | 出售把原余额加收入传给增量接口;100+20 得到 220 | 收益只加一次;交易内更新 |
| F02 | P1 | [farm.py:327](../legacy/zhenxun_plugin_farm/core/farm.py#L327)、[player.py:119](../legacy/zhenxun_plugin_farm/core/player/player.py#L119) | 收获把原经验再次传给增量接口,重复累计 | 清晰区分增量与新值 |
| F03 | P1 | [farm.py:262](../legacy/zhenxun_plugin_farm/core/farm.py#L262) | 循环中对累计经验应用当前土地加成,前面经验被再次放大 | 各地块独立计算后相加;交换地块顺序测试 |
| F04 | P1 | [user.py:102](../legacy/zhenxun_plugin_farm/core/database/user.py#L102) | updatePoint 丢弃底层失败结果,直接 True,内存可能领先落库 | 原样传播失败,提交后失效缓存 |
| F05 | P1 | [player.py:27](../legacy/zhenxun_plugin_farm/core/player/player.py#L27)、[tool.py:25](../legacy/zhenxun_plugin_farm/utils/tool.py#L25)、[command.py:53](../legacy/zhenxun_plugin_farm/command.py#L53) | 未注册玩家被缓存为空 dict,创建数据库记录后不刷新,后续判断仍未注册 | 不缓存无效玩家;注册提交后刷新 |
| F06 | P1 | [shop.py:161](../legacy/zhenxun_plugin_farm/core/shop.py#L161) | 扣款与发种分离,忽略扣款结果,发种失败不回滚 | 应用层一个事务覆盖交易 |
| F07 | P1 | [userSign.py:158](../legacy/zhenxun_plugin_farm/core/database/userSign.py#L158)、[userSign.py:229](../legacy/zhenxun_plugin_farm/core/database/userSign.py#L229) | 签到记录先提交,奖励在其后发放,中断会已签到未到账 | 唯一签到与奖励在同一事务,返回原操作结果 |
| F08 | P2 | [shop.py:194](../legacy/zhenxun_plugin_farm/core/shop.py#L194) | 只在全部出售检查锁定,指定作物分支绕开检查 | 统一可消耗库存规则 |
| F09 | P2 | [activity.py:46](../legacy/zhenxun_plugin_farm/core/activity/activity.py#L46)、[effect.py:46](../legacy/zhenxun_plugin_farm/core/activity/effect.py#L46) | 隔离加载分别因 ActivityType、Player 未定义而失败 | 标为未完成功能,不进入首版;不能仅以语法判断可用 |
| F10 | P1 | [request.py:22](../legacy/zhenxun_plugin_farm/utils/request.py#L22) | 源代码有硬编码服务令牌,任意持有源码者可取得该值 | 本轮副本已改环境变量;服务端轮换仍未完成 |
| F11 | P2 | [config.py:90](../legacy/zhenxun_plugin_farm/utils/config.py#L90)、[shop.py:243](../legacy/zhenxun_plugin_farm/core/shop.py#L243) | 批量出售选择带 name 占位符的文案却未传 name,资产更新后可能格式化失败 | 统一结果模型,先验证模板参数并用例覆盖 |
F01/F02 的例子来自源码算式,不是完整机器人运行结果。
F06/F07 的失败后果是条件性推断,尚未做数据库故障注入。
F09 已做不依赖宿主的模块定义加载,不能据此声称主插件必然启动失败。
F10 不在报告或代码中重复原令牌。
## 设计问题与待验证风险
| 编号 | 类别 | 证据与判断 | 建议验证/整改 |
|---|---|---|---|
| R01 | 并发风险 | [database.py:125](../legacy/zhenxun_plugin_farm/core/database/database.py#L125) 的 BEGIN/COMMIT 无业务事务协调;[player.py:62](../legacy/zhenxun_plugin_farm/core/player/player.py#L62) 从内存读改写 | 同一用户并发购买/收获、不同用户共享连接、任务取消测试 |
| R02 | 分层 | [userSoil.py:412](../legacy/zhenxun_plugin_farm/core/database/userSoil.py#L412) 决定星级;[userSign.py:257](../legacy/zhenxun_plugin_farm/core/database/userSign.py#L257) 绘图 | 规则上移领域/应用,绘图独立 |
| R03 | 生命周期 | [dbService.py:51](../legacy/zhenxun_plugin_farm/core/dbService.py#L51) 并发安排 init/initDB,不检查 bool 便标记 ready | 明确启动顺序和失败条件;数据库不可用时不得就绪 |
| R04 | 缓存 | [playerPool.py:67](../legacy/zhenxun_plugin_farm/core/player/playerPool.py#L67) 的线程锁只保护字典,不保护返回玩家对象的异步操作 | 数据库为权威,先移除余额写缓存,再按性能需要缓存查询 |
| R05 | 可维护性 | CDBService 和 CDBServiceLocator 两套服务入口,工具层反向加载业务对象 | 保留一个启动组装位置,明确依赖,不机械保留全局单例 |
| R06 | 外部资源 | [request.py:65](../legacy/zhenxun_plugin_farm/utils/request.py#L65) 下载直接覆盖,未验证固定版本和内容哈希 | HTTPS、大小/路径校验、暂存验证、原子切换和最后有效版本 |
| R07 | 扩展机制 | [event.py:60](../legacy/zhenxun_plugin_farm/event/event.py#L60) 事件槽吞异常后继续 | 必需状态更新不依赖这种可失败通知;事件限定提交后副作用 |
“农场下阶段”虽未见入口管理员检查,但 nextPhase 有调试开关且当前
默认 False;本轮不将其认定为默认可利用的权限漏洞。
未来调试功能应显式授权且不进入普通用户命令集。
## 复核与测试优先级
先写行为级回归:出售余额、收获经验、首次注册立即使用、
交易失败不改变任一资产、签到不重复发奖、指定与批量出售锁定一致。
再补并发、时间、迁移和三宿主加载测试。
本轮没有修复 F01–F09/F11,也没有宣布审查通过可发布。
迁移副本唯一安全修正为 F10,旧项目仍保持原样。
+41
View File
@@ -0,0 +1,41 @@
# 待确认与补充问题
这些事项会改变用户资产、玩法和部署结果。文档中的建议不是已确认需求;
本轮初始化和保全不依赖它们,正式业务实现前需收敛关键项。
| 决策 | 建议起点 | 为什么要确认 |
|---|---|---|
| 农场归属 | 每个独立部署自有数据;群共享范围明确配置 | 决定注册唯一键、偷菜范围与迁移 |
| 多框架关系 | 先支持分别部署和迁移,不自动在线互通 | 联机会改变存储与服务架构 |
| 账号迁移 | 显式平台命名空间与人工确认映射 | QQ 官方标识与 OneBot ID 不宜自动合并 |
| 存量资产 | 默认保留并记录异常,另议补偿 | 旧逻辑有增发,无法从余额准确逆推 |
| 外部金币 | 真寻保留可选接入;其他框架默认关闭 | 外部钱包无法由本地事务保证原子性 |
| 点券和星级 | 先核对现有用途、成本与升级公式 | 涉及经济平衡与数据兼容 |
| 签到资源 | 首先保证内置/本地配置可用,联网更新可选 | 远程服务停机不应让基本玩法不可用 |
| 资源分发 | 精简基础资源;需要时使用固定版本扩展包 | 旧资源 ZIP 超 AstrBot 16 MB 市场限制 |
| 渲染 | 文本必备,图片可选且失败降级 | 宿主、字体、浏览器依赖和性能不同 |
| 兼容基线 | 保留旧指令清单;Python/宿主版本经矩阵实测确定 | 旧 README 的 3.10+ 不等于三框架共同最低版本 |
| 发布顺序 | 真寻先稳定,之后普通 NoneBot、AstrBot | 利用现有宿主验证闭环,控制变更范围 |
| 发布仓库 | 使用给出的三个现有仓库,接管前比较现有代码 | 三仓库不为空,不能直接覆盖 |
| 主仓库远程 | 用户后续提供独立 farm 地址 | 本轮只建本地 Git,不误用发布仓库 |
| 发布授权 | 首次候选 PR 审查,稳定后再议自动发布 | 本轮未授权远程覆盖、推送或发布 |
| 跨平台 OS | 建议 Windows + Linux;macOS 有需求再验收 | 路径大小写、字体、浏览器和时区需分别测试 |
| 素材许可证 | 核对图片、字体、HTML 和借用工具来源 | 代码 GPLv3 不自动证明所有素材可分发 |
| 数据运维 | 定期备份、保留策略、恢复演练和脱敏诊断 | 游戏资产需要可恢复性和隐私保护 |
## 容易遗漏的技术约束
- 从旧仓库自动更新到新布局时,插件安装器是否删除旧文件;
旧入口残留可能重复加载,必须进行“旧版→新版”真实升级演练。
- 多目标发布可能部分成功,需要按目标重试和状态清单。
- 插件降级不等于 schema 降级;必须定义最低可读写 schema。
- 网络重试、平台重复投递、图片发送失败不能再次发奖或扣款。
- 资源目录只读部署场景必须支持,把可写缓存放宿主数据目录。
- 同一宿主同时安装相关插件时,模块名称和第三方依赖可能冲突;
插件私有打包只解决前者。
- Python、宿主框架、数据库 schema、作物规则和资源版本分别记录,
不混用一个远程浮点版本比较所有兼容关系。
- 发布仓库里的现有 star、issue、tag 和许可证要保留;不能 force push。
- 子仓库是概念上的发布仓库,不使用 git submodule,也不把本地克隆
提交进主仓库。
- CI 中的密钥不写源码;旧源码中暴露的服务令牌需服务端轮换。
+48
View File
@@ -0,0 +1,48 @@
# 本轮验证与交付边界
日期:2026-10-15。执行 Python:3.12.14;未安装或启动三种宿主。
新工具还以 Python 3.10 语法规则解析旧代码;这不代表三框架共同支持
Python 3.10,最低运行版本需在后续兼容矩阵中确认。
## 已完成
| 检查 | 结果 | 证据 |
|---|---|---|
| Git 初始化 | main 分支,本地仓库,无远程、无提交或推送 | Git 状态;repository-checks.json |
| 迁移完整性 | 827 文件均匹配复制 SHA-256 | scripts/check_baseline.py |
| 来源保持 | 827 文件的旧项目来源哈希未变化 | repository-checks.json |
| Python 语法 | 35 个基线文件通过 | baseline-checks.json、校验脚本 |
| JSON 语法 | 4 个基线配置/版本文件通过 | 校验脚本 |
| 静态数据库 | 两库 quick_check=ok,仅 plant/sqlite_sequence 表 | 校验脚本 |
| 未完成活动模块 | 隔离加载确认两个 NameError;作为已知缺陷记录 | baseline-checks.json、F09 |
| 忽略规则 | 29 类路径均符合预期;827 基线文件未误屏蔽 | repository-checks.json |
| 新工具语法/行长 | 通过;无超 80 字符行 | repository-checks.json |
| 资源 ZIP 测量 | 26,084,694 字节;仅体积探测,未生成安装包 | baseline-checks.json |
| 本地克隆删除 | 三个副本和空父目录均已删除,无子模块 | repository-checks.json |
| 令牌处理 | 迁移副本从环境变量读取;未复制原令牌 | legacy-manifest.json 的唯一差异 |
| 换行保护 | legacy/** -text,避免 Git 检出改变基线字节 | .gitattributes |
本地文档链接复核通过,无缺失目标。校验工具的错误路径也已验证:
模拟 827 个哈希失配均被检测;越界的清单目的路径被拒绝。源码图覆盖存在 metadata_changed 提示,
结论均以直接读取的源码为依据,不把代码图的缺边当作无调用证据。
## 明确未完成
- 旧业务缺陷修复、新核心、多框架插件入口和实际宿主加载。
- 真实数据库事务故障注入、并发压测和全部玩法回归。
- 真实玩家数据库迁移、账号绑定、跨框架数据共享与外部金币对账。
- 跨仓库自动发布、Actions 权限配置、PyPI、Release、商店审核。
- 主仓库远程设置、首次提交、推送或覆盖任一发布仓库。
- 原服务端令牌轮换,素材和字体授权清单、资源瘦身。
## 后续复现
```text
python scripts/check_baseline.py
git status --short
git check-ignore -v runtime/farm.db
git check-ignore -v .release-workspaces/example/.git/config
```
两条 check-ignore 用于观察忽略规则;路径无需真实存在。
脚本不导入插件、不发网络请求、不读玩家数据库。
+31
View File
@@ -0,0 +1,31 @@
# 文档索引
记录日期:2026-10-15。状态:已形成设计草案,待关键产品决策确认;
业务重构、多框架接入、发布流水线和真实数据迁移尚未实施。
| 文档 | 用途 |
|---|---|
| [01-roadmap.md](01-roadmap.md) | 长期目标、实施顺序、里程碑与验收 |
| [02-architecture.md](02-architecture.md) | 分层、目录、依赖、接入与接口设计 |
| [03-business-rules.md](03-business-rules.md) | 身份、货币、库存、作物、事务与幂等 |
| [04-release-design.md](04-release-design.md) | 一个主仓库、三个发布仓库、分包与同步 |
| [05-migration.md](05-migration.md) | 旧代码复用、数据升级、兼容与回滚 |
| [06-code-review.md](06-code-review.md) | 源码证据、缺陷等级、验证状态与修复方向 |
| [07-decisions.md](07-decisions.md) | 需要补充的产品和运维决定 |
| [08-validation.md](08-validation.md) | 本轮实际验证及尚未验证的范围 |
| [legacy-manifest.json](legacy-manifest.json) | 827 个复制文件的来源与 SHA-256 |
| [repository-checks.json](repository-checks.json) | 忽略规则、文档链接、工具错误路径与清理结果 |
| [baseline-checks.json](baseline-checks.json) | 语法、隔离加载、ZIP 体积探测结果 |
| [repository-inventory.json](repository-inventory.json) | 曾克隆仓库的历史元数据;本地副本已按用户要求删除 |
| [task_plan.md](task_plan.md) | 本轮任务及完成状态 |
| [findings.md](findings.md) | 调查发现 |
| [progress.md](progress.md) | 执行记录 |
## 阅读与使用约定
- “已确认”必须有源码、命令或文档来源;“建议”不能当作已接受需求。
- 文档中的目标结构是设计,不表示对应代码已实现。
- 发布仓库是分发目标,不是 Git 子模块;各框架使用相互独立的插件包。
- 主仓库远程地址尚未提供;不将任一插件发布仓库误设为主仓库 origin。
- 用户已撤回拉取要求,且要求删除本地克隆;三个本地检出已删除,不再访问远程。
- 本轮仅修正迁移副本中的硬编码凭据;业务缺陷记录在审查报告,没有隐式修复。
+20
View File
@@ -0,0 +1,20 @@
{
"python": "3.12.14",
"python_syntax_files": 35,
"syntax_errors": [],
"isolated_module_probes": [
{
"path": "core/activity/activity.py",
"result": "NameError",
"detail": "name 'ActivityType' is not defined"
},
{
"path": "core/activity/effect.py",
"result": "NameError",
"detail": "name 'Player' is not defined"
}
],
"baseline_zip_bytes": 26084694,
"zip_is_installable_plugin": false,
"note": "Size probe only. No framework, scheduler, network or player database started."
}
+27
View File
@@ -0,0 +1,27 @@
# 调查发现
## 已确认事实
- 新主目录 D:/Work/farm 起初为空,现已本地初始化为 main,无远程。
- 源旧项目 Beta 提交 b015c6c1997f146f651b677382980d338a306bb2。
- 源业务文件本轮未修改;复制 827 文件,35 个 Python 文件。
- 两个作物数据库只有 plant 和 sqlite_sequence 表,quick_check 正常。
- 基线 ZIP 约 24.9 MiB,超过 AstrBot 发布文档所述市场包 16 MB 上限。
- 两个活动模块虽能语法解析,但隔离加载分别发生未定义类型 NameError。
- 硬编码服务令牌未复制进新仓库,副本改读 FARM_SERVICE_TOKEN。
- 出售、经验、失败返回、注册缓存等确定性问题见审查 F01–F11。
- 三个用户给出的仓库都已有 main 历史,与本地 Beta 布局不同;
已按用户最新要求删除本地克隆,只保留历史元数据和地址。
## 设计建议
- 主仓库唯一开发源,每个框架发布包携带私有、同版本共享核心。
- 领域/应用/存储/展示/接入职责清晰,首期不建立复杂微服务。
- 数据库为业务权威,应用用例拥有事务,操作具备幂等标识和流水。
- 首期独立部署,跨框架在线共享数据是单独需求。
- 发布使用白名单和可审查候选,不直接清空三个已有发布仓库。
## 待确认
身份和群共享范围、存量资产处理、外部经济、资源分发、最低宿主版本、
主仓库远程地址及发布授权,详见 07-decisions.md。
+26
View File
@@ -0,0 +1,26 @@
{
"status": "passed",
"files": 827,
"python_syntax_files": 35,
"json_files": 4,
"catalogues": [
{
"name": "plant.db",
"quick_check": "ok",
"tables": [
"plant",
"sqlite_sequence"
]
},
{
"name": "plant-test.db",
"quick_check": "ok",
"tables": [
"plant",
"sqlite_sequence"
]
}
],
"errors": [],
"scope": "integrity and syntax only; no host or gameplay verified"
}
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
# 执行记录
## 2026-10-15
1. 定位空 farm 目录,核对旧项目分支与源提交。
2. 选择 docs 作为唯一计划位置,初始化 Git main。
3. 读取规划与审查要求,代码图查询后对关键问题核对源码。
4. 复制 827 个受版本管理文件与许可证,保留旧项目。
5. 复制前移除硬编码令牌,记录唯一源码差异与逐文件 SHA-256。
6. 测量压缩体积,执行语法、静态数据库与隔离模块检查。
7. 根据用户补充记录三个发布仓库地址并完成 clone;
收到停止后不再远程操作,收到删除要求后验证精确路径并删除三个副本。
8. 完成架构、业务、发布、迁移、审查、决策与验证文档。
9. 建立 Python/农场忽略规则、跨平台换行策略、职责目录和离线校验工具。
10. 离线校验通过:827 哈希、35 Python、4 JSON、两静态库。
11. 29 类忽略规则符合预期;所有基线文件可被跟踪;源哈希未变化。
12. 新工具无超长行;发布检出目录已不存在,无 .gitmodules。
13. 文档链接、差异和工具错误路径在最后交付核对中记录到验证结果。
未实现新业务、未提交或推送、未配置远程发布权限。
+19
View File
@@ -0,0 +1,19 @@
{
"git_branch": "main",
"git_remote": "",
"ignore_cases": 29,
"ignore_errors": [],
"ignored_baseline_files": [],
"broken_local_links": [],
"new_python_overlong_lines": [],
"source_hash_drift": [],
"local_release_workspace_exists": false,
"gitmodules_exists": false,
"helper_negative_checks": {
"hash_mismatch_detected": 827,
"destination_traversal_rejected": true
},
"legacy_text_attribute": "legacy/zhenxun_plugin_farm/command.py: text: unset",
"untracked_candidate_files": 858,
"embedded_git_directories": []
}
+93
View File
@@ -0,0 +1,93 @@
{
"checked_on": "2026-10-15",
"repositories": [
{
"name": "zhenxun_plugin_farm",
"url": "https://github.com/Shu-Ying/zhenxun_plugin_farm.git",
"local_path": ".release-workspaces/zhenxun_plugin_farm",
"branch": "main",
"commit": "ac495ad6e94f414f5a642a0429f51e7affad3b2a",
"remote_head": "origin/main",
"status": "",
"tracked_files": 720,
"root_entries": [
".gitignore",
"LICENSE",
"README.md",
"__init__.py",
"command.py",
"config",
"config.py",
"database",
"dbService.py",
"event",
"farm",
"json.py",
"log",
"request.py",
"resource",
"tool.py"
],
"nested_agent_rules": [],
"local_exists": false,
"observation": "historical metadata collected before user requested deletion"
},
{
"name": "astrbot_plugin_farm",
"url": "https://github.com/Shu-Ying/astrbot_plugin_farm.git",
"local_path": ".release-workspaces/astrbot_plugin_farm",
"branch": "main",
"commit": "1f47aa84611e23a8f0814b9a9d236386a7bf4e13",
"remote_head": "origin/main",
"status": "",
"tracked_files": 727,
"root_entries": [
".gitignore",
"LICENSE",
"README.md",
"_conf_schema.json",
"cfg.py",
"config",
"database",
"dbService.py",
"event",
"farm",
"json.py",
"log",
"main.py",
"metadata.yaml",
"request.py",
"requirements.txt",
"resource",
"tool.py",
"zhenxun_utils"
],
"nested_agent_rules": [],
"local_exists": false,
"observation": "historical metadata collected before user requested deletion"
},
{
"name": "nonebot_plugin_farm",
"url": "https://github.com/Shu-Ying/nonebot_plugin_farm.git",
"local_path": ".release-workspaces/nonebot_plugin_farm",
"branch": "main",
"commit": "4fe60a6bde22375a7f81d2ed60aebfdb4f5fe93f",
"remote_head": "origin/main",
"status": "",
"tracked_files": 720,
"root_entries": [
".github",
".gitignore",
"LICENSE",
"README.md",
"nonebot_plugin_farm",
"pyproject.toml"
],
"nested_agent_rules": [],
"local_exists": false,
"observation": "historical metadata collected before user requested deletion"
}
],
"current_local_state": "deleted-at-user-request",
"network_actions_allowed": false
}
+47
View File
@@ -0,0 +1,47 @@
# Farm 主仓库初始化计划
日期:2026-10-15。负责人:当前主 Agent。
## 目标与状态
本轮初始化与设计交付已完成。业务重构尚未开始,正式产品决策仍待确认。
建立一个开发主仓库、多框架发布仓库的长期方案;保留旧插件源码与资源;
完成 Git、忽略规则、设计和源码审查文档。
## 完成阶段
- [x] 定位 D:/Work/farm;原为空目录。
- [x] 初始化本地 Git,main 分支;未设远程,未提交或推送。
- [x] 复制 827 个旧文件,生成来源清单;副本移除硬编码凭据。
- [x] 完成架构、目录、业务逻辑、发布与迁移规划。
- [x] 完成源码审查、待确认项与风险说明。
- [x] 验证哈希、Python/JSON 语法、静态库和忽略规则。
- [x] 按补充要求记录三个发布仓库地址。
- [x] 用户撤回拉取并要求删除后,删除三个已克隆副本,停止远程访问。
- [x] 本地文档索引与校验结果交付。
## 不属于本轮的工作
真实多框架业务实现、自动发布、远程提交、发布仓库接管、真实用户数据
迁移和服务端令牌轮换,分别按路线和授权推进,不计为本轮已完成实现。
## 约束
- 旧项目 D:/Work/zhenxun_plugin_farm 保持不变。
- 基线:Beta,b015c6c1997f146f651b677382980d338a306bb2。
- 真实玩家数据、凭据、运行时缓存和 Git 元数据不复制进主源码。
- 文档区分事实、设计建议、待确认项与已完成修改。
- 三个发布仓库仅记录地址,不再 clone/fetch/pull/push。
## 执行异常与处理
| 情况 | 处理 |
|---|---|
| 默认命令环境曾有 MXC 启动错误 | 使用针对用户授权目录的提升执行 |
| 规划解析脚本被签名策略拒绝 | 不改系统策略,显式固定 docs 规划位置 |
| 空目录尚非 Git 仓库,diff 失败 | 初始化后验证 |
| 文档首次检查时 08-validation.md 尚未创建 | 创建后重新检查链接 |
| 旧活动模块 NameError | 记录为已确认缺陷,不混为本轮失败 |
| 用户要求停止拉取时三个 clone 已完成 | 如实说明,收到删除要求后逐个校验路径并删除 |
没有尝试绕过用户停止拉取要求,也没有执行远程发布。