Commit Graph
39 Commits
Author SHA1 Message Date
eaiadmin 90031b75f3 docs: 重构仓库文档目录并迁移训练素材
按当前架构重组 docs 目录,统一中文命名与目录分层,并将训练原材料迁移到独立目录以保持架构文档边界清晰。
2026-09-22 23:23:16 +08:00
eaiadmin 9288f0215a fix: allow office execution registry to register handlers
Keep the office execution registry mutable during frontend startup so login can finish routing to the home page without crashing.
2026-09-21 13:20:56 +08:00
eaiadminandClaude Code e8aedd50d2 refactor: 后端仓库层更名为数据访问层(internal/repository → internal/dal)
「仓库层」是 repository 的直译,中文里与「代码仓库 / git 仓库」同词,
而这一层做的事就是数据访问。名字改成它实际在做的事。

改名口径(纯机械替换,无逻辑改动):
- 包:internal/repository → internal/dal(package repository → package dal)
- 类型:XxxRepo → XxxDAO(TaskRecordDAO / SpecialistDAO / PositionDAO …)
- 变量:xxxRepo → xxxDAO
- import 路径、包限定符、日志前缀 [repository] → [dal] 同步
- 注释里的「仓库层」→「数据访问层」;core.go 包注释补上 DAL/DAO 全称

命名规范补登(AR09 是命名问题的最高依据,改了名就得回去登记):
- AR09 §3.1 术语表新增「数据访问层 dal / DAO」一行
- AR09 §5.6 缩写表新增 DAO / dal —— 原文是「只有下表内的缩写允许使用」,
  不登记就是自己破自己的规矩
- PROJECT_STATE.md 新增 D27 记录本次更名决策

验证:全部在 db 副本上做,生产库 data/eai_agentplatform.db 未触碰。
- 等价性对照:拿 HEAD 源码 + 仅改名 造出第二棵树,两棵树各自起
  httptest 服务跑同一份探针(60 个 GET + 13 个写/回读,覆盖专员/技能/应用/
  任务/交付物/项目/岗位/考试/知识/积分/管理端只读等),逐端点比对响应体:
  73 项里 52 项字节完全一致、21 项仅运行期时间戳不同、内容差异 0。
- 探针非空:往改名后的树注入「SpecialistDAO.List 限 3 条」变异,
  /api/specialists 立刻被抓出 —— 证明上面那个 0 不是没测到。
- 暂存区自洽:把索引整个导出成源码树,go build / go vet / go test ./... 全绿。
- gofmt:因 import 排序变化而错位的 19 个文件已修;另 2 个文件(skill_definition.go、
  seed.go)的格式问题是工作区里别人的在制品带来的,未替其改动。

未纳入本次提交:工作区里正在进行中的「文生语音技能 + 技能展示色/交互卡」
(tts_handlers.go、text_to_speech/manifest.go、skillCatalog.js 等),
以及 router.go / skill_definition.go / seed.go 三个文件里属于该在制品的改动 ——
这三个文件只把「改名那一版」放进索引,工作区原样保留。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 09:19:21 +08:00
eaiadminandClaude Code 1875e7dd4c refactor: 后端仓库层收口(A6:公众号助手技能包)
wechat_official_account 包原先直接拿 store.DB 读写 27 处,是仓库里仅剩的最大
一块。收口后该包不再引用 store:任务/运行记录/交付物/专员四类模型用的是 A4 就
已有的仓库,只有两个包内私有模型(文章状态、热点缓存)新增了仓库。

顺带修掉一处三态混淆:原 loadOfficialAccountArticle 把「读取出错」和「还没有」
合并成同一条路(`if err == nil { return article }`,其余一律往下建新行),于是
读路径(GET workflow / 导出 / 执行步骤)上一次读取失败会去盲目 INSERT,撞上
task_id 唯一索引才失败 —— 那是运气不是设计。改成 FindByTaskID 明确返回三种
结果,读失败就报错,不再新建。

行为变化(有意,不是等价重构):
- 热点缓存读失败、产物/运行记录查询失败,原先 web.Fail 成错误,现在按仓库层
  bool 风格降级成「空」:调用方分别走不依赖热点的兜底选题路径 / 返回空时间线。
- 因此 loadFreshOfficialAccountHotspots 及其调用链上的 error 出口恒为 nil。
  留着是为了不再往上传导签名改动,已在注释里写明这是行为变化。

验证(脚手架用完即删):
- 真实请求:db 副本 + httptest 走完整路由,覆盖建任务/读工作流/改配置重置/
  归属隔离(非归属人 404)/唯一键下不重复建文章行/重置后旧 run+artifact 清空。
- 仓库层直测:热点过滤(0 分、过期、跨业务域)、排序三级兜底、LIMIT 40、
  同 URL 不同源必须是两行、FindByTaskID 三态、DeleteByTask 只清本任务。
- 14 个变异全部被杀死(去掉各过滤条件、ORDER BY、LIMIT、冲突键里的 source_key、
  空切片保护;三态退化成两态;DeleteByTask 丢掉 task_id;归属校验改成不过滤)。
  其中 M6 第一轮活下来,暴露出 R3a 用同一个 source_key、单 url 也能匹配 ——
  是断言写空了,补了「同 URL 不同源必须两行」才真正测住。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 08:55:50 +08:00
eaiadminandClaude Code 9157df40f3 fix: 布尔字段的「没传」与「传 false」被库默认值合并
三处同一形状的缺陷:模型的 bool 字段带 `gorm:"default:true"`,而 GORM 在
Create 时会跳过「带 default 标签的零值字段」,于是 Go 里的 false 被当成「没填」,
改由库默认值 true 生效。对象显式设的 false 被持久层改写成 true。

- skill_definition.exposed_to_user
- xapp_definition.exposed_to_user
- position_knowledge.is_mandatory

前两处有两个方向的病症:

1. 创建接口设不出 false —— 管理员建一个「不暴露给用户」的技能/应用,
   接口返回 200、看着成功,库里存的是 true。
2. **更新接口会静默撤下** —— 前端 admin 表单根本不发 exposed_to_user
   (只读不写,见 skillCatalog.js / xappCatalog.js),而 PUT 对每个字段
   无条件覆盖,于是管理员改个标题就把技能/应用从用户目录里摘了。
   这条是线上正在发生的,比第一条更狠。

position_knowledge 同样:前端的必学/选学 el-switch 怎么拨都存成必学。

修法是拿掉那层「持久层替对象拿主意」:

- 模型去掉 `default:true`,对象说了算,仓库原样落库;
- 请求 DTO 改 *bool,把「没传」和「传 false」分开 —— 三态只存在于线上,
  `not null` 的列没有「未设置」态,所以不进模型;
- 默认值归接口契约,放 handler:新建时没传按 true(与种子数据、前端
  `exposed_to_user !== false` 口径一致),更新时没传保持原值
  (前端不发这个字段,不能因为一次无关编辑就改变可见性)。

没选的两个方案:给 Create 加 Select("*") 是把 GORM 的零值规则泄漏进 HTTP
适配层,只盖住症状还得每处创建路径都记得;模型改 *bool 则是给一个
不存在的领域状态造了个位置,还让 JSON 多出 null。

验证(tmp_vfy_fix,临时程序,验完已删):真实路由 + 真实 HTTP,跑在数据库
副本上,39 条断言全绿。同一份断言在修复前跑出 6 条红(S1/X1/P2:显式 false
存成 true;S9/X9:更新不带该字段把 true 静默改成 false),确认断言确实在测
这个修复而不是装饰。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 02:17:19 +08:00
eaiadminandClaude Code c5af5084b1 refactor: 后端仓库层收口(A5:技能/应用定义 + 用户应用中心)
D25 定的对象层三类一级对象(专员 / 技能 / 应用),A4 收了专员,这次是
技能与应用。原先是 handler 里直接 store.DB.Create/Save/Delete,现在统一走
repository,与 A1~A4 同一形状:仓库方法返回 bool,三态参数用 *bool 表达。

新增:
- repository.SkillDefinitionRepo / XAppDefinitionRepo —— List / GetByID /
  GetByKey / Insert / Update / Delete
- repository.UserXAppCenterRepo —— 收藏/最近使用/自定义应用,每人一份

两处刻意偏离既有惯例,都写了理由在代码里:

1. List(state string, exposedToUser *bool) 不在仓库里定默认值。「不传 state
   就只看 active」是列表接口的契约,解析 query 参数是 handler 的活;仓库只
   执行过滤。exposedToUser 用 *bool 而非 bool,因为「不传该参数」与「传
   false」语义不同——前者要全量,压成 bool 会把不传当成 false。

2. UserXAppCenterRepo.FindByUser 返回 (row, error) 而不是 bool。「没找到」在
   这个仓库是有意义的第三态:表示该用户还没配过、调用方要新建一份。若压成
   bool,一旦读取真出错(SQLite 本地锁等待是常事)就会被当成「没配过」,转而
   写一份空白配置,把用户已有的收藏和最近使用抹掉。

技能与应用的读接口共用同一个仓库变量,只声明一处(skillDefinitionRepo 留在
admin_handlers.go)——两份变量持有同一仓库时,测试里覆写一份、另一份照旧,
行为会静默分叉。

A5 范围内的 store.DB 直用已清零;skills/api/office_handlers.go 里仍有 3 处,
是 store.DB.Transaction,QueryBuilder 不带事务,留着别动。

验证(tmp_vfy_a5,临时程序,验完已删):真实路由 + 真实 HTTP,跑在数据库
副本上。55 条断言全绿,覆盖技能/应用的列表三态、按 key 取、增改删、404 路径、
用户应用中心的空配置/覆盖写/多用户隔离。

另有 14 条变异测试确认断言真的会红(13 捕获 / 1 设计上不可观测),其中
排序断言原本是假的:三条种子的插入顺序恰好也是 sort_order 升序,删掉
ORDER BY 照样绿。补了一条「sort_order 更小但插入更晚」的记录才透光。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 02:11:00 +08:00
eaiadmin 71f1b6246f docs: RS02 补记 specialist.version 是展示字段而非版本快照
对照表里「定义版本快照 = 无」这一格容易被 specialist 表的 version
字段误判成「有」,补一句说明:它是 admin 直接赋值的自由文本,
无快照语义,skill_definition / xapp_definition 连这个字段都没有。
2026-09-19 02:10:55 +08:00
eaiadminandClaude Code 481ebeaf3e docs: 外部智能体平台架构对照调研(RS02)入库
为六层架构「第 1/2/3 层补缺」提供外部对照基准,与既有 RS01(WorkBuddy
Skill/RPA 学习)同属 docs/09_Research 调研系列。

六条发现:行业几乎不讲「层」、定义态/运行态强制分离、编排正在「去图化」
且已分裂成图派与 ReAct/交接派、Skill 包已经标准化、本体层是选答题但做了
就是护城河、连接层正在被 MCP 统一;另附国内企业级平台的特殊性一节,
其中含与 pj0235「三对象」同构的官方口径。

文首已标明状态为调研稿,仅供架构决策参考,尚未形成实施结论。
文中引用的 6 份关联文档已逐一核对存在。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 02:01:01 +08:00
eaiadminandClaude Code 4f31e0c438 refactor: 后端仓库层收口(A4:任务/项目/笔记/专员/动作定义)
把 B 档(此前尚无仓库的对象)的 api 裸查询收进仓库,api 层裸 store.DB
从 162 降到 96(口径:internal/ 下非测试 .go,不含 internal/repository/ 自身)。
新增 7 个仓库:TaskRecordRepo / TaskArtifactRepo / TaskRunRepo / ProjectRepo /
StudyNoteRepo / SpecialistRepo / ActionDefinitionRepo。

按对象补齐的方法:
- TaskRecordRepo:GetByID / GetByIDForOwners / ListBySpecialistKey / ListByOwners /
  ListByProject / CountBySpecialistKey / ClearProject / DeleteCascade
- ProjectRepo:GetByIDForOwners / ListByOwners
- StudyNoteRepo:ListByUser / GetByID
- SpecialistRepo:GetByKey / GetByID / Query / List / CountByKey
- TaskArtifactRepo / TaskRunRepo:GetByID / ListByTask
- ActionDefinitionRepo:List / GetByID / GetByKey

几条口径改由仓库单点持有,避免各处手写漂移:
- 归属过滤抽成 ownerScope:owners 为空时套恒假条件(空集),绝不退化成全表。
  specialists/runtime 的 MyTaskQuery / ProjectQuery 随之删除,调用方改用
  MyTaskOwners + 仓库方法 —— 任务与项目共用同一套归属口径。
- 「任务 + 交付物 + 运行记录三张表同事务级联删除」从 handler 收进 DeleteCascade,
  不留没有任务的孤儿交付物;删项目只解除其下任务的 project_id 归属(置 NULL,
  不是 0),不删任务本身 —— 任务是「做过的事」,删一个分组不该把它一起抹掉。
- 专员目录的 state 档位(默认 active / all 仅管理员 / system / 其它精确匹配,
  且除显式要 system 外一律排除 system 记录)收进 SpecialistRepo.List。
- GetByKey 有意不过滤 state:调用方口径不同(建任务时要能查到,对话取 prompt
  时要拒绝 inactive),口径留在调用方,仓库只负责取数。顺带把「按 key 找专员」
  从 4 个文件里各写一遍收敛成一处。
- ActionDefinitionRepo.List 不替调用方定 state 默认值 ——「不传 state 就只看
  active」是列表接口的契约,由 handler 解析 query 后传入。
- StudyNoteRepo.GetByID 不判归属,越权检查留在 handler(那里能把「不存在」与
  「不是你的」分别回成 404 / 403)。

保留未动:skills/api/office_handlers.go 里两处 store.DB.Transaction —— 运行记录
与交付物要在同一个事务里落库,QueryBuilder 不带事务,维持原样并就地注明。

验证:go build ./... 与 go vet ./... 干净,go test ./... 6 个包全绿。
另用独立验证程序走真实路由 + 真实 HTTP,对数据库副本跑 148 项断言全绿
(覆盖跨用户越权 404、空 owners 退化成空集、级联删除、解除归属置 NULL、
笔记按用户隔离、专员 key 唯一性排除自身、管理员 state=all 仍排除 system 等)。

另对其中 10 条关键语义做了变异测试:逐条注入反向实现,确认断言确实会失败,
捕获 10 / 漏掉 0。变异测试同时暴露并修掉了验证体系自身的两个漏洞:
- 「state=all 排除 system」这条规则此前没有任何断言能观察到 —— 默认档被
  state=active 挡着、system 档被 state=system 挡着,删掉实现也不会红;
- 变异驱动只跑 HTTP 断言、不跑 go test,导致针对单元测试注入的变异
  (拒绝已下线专员的 prompt)永远逮不到。

验证程序为一次性脚手架,验证完成后已删除(tmp_vfy_b/)。
原始 data/eai_agentplatform.db 全程未触碰(mtime 仍为 2026-09-17 15:14)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 01:55:26 +08:00
eaiadminandClaude Code 19cf6fb5f2 refactor: 后端仓库层收口(A3:考试/部门/学习/证书/档案/公司介绍)
把 A 档剩余对象的 api 裸查询全部收进仓库,api 层裸 store.DB 从 182 降到 99,
剩下的全是 B 档(任务/项目/笔记等尚无仓库的对象)与 C 档(报表聚合查询)。

按对象补齐的仓库方法:
- QuestionRepo:List 重写(status 档位改为显式 all/空/具体值)、
  ListByIDs(判分不过滤 status)、ListActiveByIDs(下发剔除停用)、
  ActivePool(抽题口径,主流程与蓝图共用)、DomainMap(能力雷达反查域)
- ExamPaperRepo.List;ExamRecordRepo.ListByUserChronological(趋势图正序)
- DepartmentRepo.ListByStatus / CountByName
- UserRepo.ListEmployees / CountActiveByDepartment / RenameDepartment
- LearningProgressRepo.ListAll;CertificateRepo.ListAll / GetByExamRecord
- MediaFileRepo.ListApprovedByBindType

顺带修掉两处隐患:
- CertificateRepo.GetByUserAndExam 按不存在的 exam_id 列查,一调即 SQL 报错,
  换成按 exam_record_id 的 GetByExamRecord(颁发幂等本来就该按考试记录)
- exam.go 与 system.go 各声明了一个 ExamRecordRepo 变量,同一个仓库两份变量
  会导致测试覆写时行为分叉,统一为一个 examRecordRepo

考证来源(趋势图正序 vs 列表页倒序)与抽题口径(岗位蓝图/岗位知识映射两条路径)
各自抽成单一出处,避免两处手写漂移。聚合与百分比计算仍留在 handler,未搬进仓库。

验证:tmp 验证程序走真实路由 + 真实 HTTP,对 DB 副本跑 111 项断言全绿
(覆盖停用题仍可判分、错题重练剔除停用题、趋势正序、改名同步 user.department
且 updated_at 仍刷新、未通过的正式考不发证书、公司介绍只出 approved 素材等)。
另对其中 8 条关键语义做了变异测试:逐条注入反向实现,确认断言确实会失败,
并因此发现并修掉验证程序自身一处漏洞(写语句的约束错误只在 rows.Err() 浮出,
原先未检查,导致一条断言实为空断言)。

原始 data/eai_agentplatform.db 全程未触碰,md5 复核一致。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 01:41:33 +08:00
eaiadminandClaude Code 14f303459e refactor: 后端仓库层收口(A1:课程/产品/素材)+ 收进工作区既有对象化重构
本提交含两部分。第一部分是本轮工作;第二部分是此前一直留在工作区、
从未提交的对象化重构,与第一部分在文件上互相咬合(internal/repository
整个包都是未跟踪状态,且 api 层已有文件引用它),无法拆成两个可编译的提交。

一、仓库层收口 A1 批(本轮工作)

把 api 层手写的 store.DB 查询收进具名仓库方法,只给真正获益的对象做方法,
不机械包裹全量。本批迁移 22 处裸查询(courses.go 9 / media.go 12 / products.go 1),
新增方法:

- MediaFileRepo.ListByBind / ListForAudit / MarkExtracted
- KnowledgeChunkRepo.CountByMediaFile
- ProductRepo.GetVisibleByID

两条业务口径改由仓库单点持有,避免各处手写漂移:
「只有 approved 素材出现在课程详情」与「已停用产品不在课程详情露出」。

修掉两个真实缺陷:
- ProductRepo.GetByID 缺 Where 条件。此前 GET /api/products/{id} 对任意 id 都返回
  第一条产品、对不存在的 id 返回 200,且 PUT /api/products/{id} 会覆盖第一条产品
  —— 数据损坏级。全仓扫描确认这是唯一一处同型写法。
- ProductRepo.Delete 写 status="deleted",而 DELETE 处理器文档与回包都声称
  "inactive",接口在说谎;管理员用 status=all 拉列表会看到前端不认识的状态。
  已对齐为 inactive(与 CourseRepo.Delete 一致)。

删除 8 个零调用且列名不存在的死方法(一调即 SQL 报错):
- media_file 上的 file_path / file_type / approval_status 三列并不存在,
  GetByPath / ListByType / UpdateStatus 全废
- knowledge_chunk 上的 space_id 列不存在(模型早已改为 knowledge_space_key),
  List / Total / ListBySpaceIDs / DeleteBySpace / SearchByVector 全废
取舍边界:能对当前 schema 跑通的死方法保留,跑不通的删或修。

CourseRepo.List 补齐 status=all 档(此前传给它会当作 status='all' 过滤出空列表)。
该方法此前零调用,现与产品列表语义对齐。

验证:go build ./... 与 go test ./... 全绿;另用真实 HTTP 请求验证 34 项
(课程 17 / 产品 3 / 素材 14),跑在数据库副本与独立 KB_DATA_DIR 上,
含 multipart 真上传 → 审批 → pdftotext 提取 → 分片入库的完整链路。

二、此前未提交的对象化重构(非本轮工作)

- 新增 internal/repository 仓库层、connectors、skills、specialists、xapps、jsonutil,
  model/task_record|task_run|task_artifact、api/task_runtime|action_definition|chat_message
- 删除 api/app_definition、connectors、my_app_center、notification、office_skill、
  export_docx|pptx|xlsx、official_account_* 等,随 XApp/Skill/Specialist/Connector
  可插拔打包方向(AR10/AR11)调整
- 资产目录归位:backend-go/knowledge_source → assets/knowledge/source、
  training_materials → assets/training/materials;README 内相对路径同步加深两级;
  deploy env 补 ASSET_ROOT_DIR 并改 KNOWLEDGE_SOURCE_DIR / TRAINING_MATERIALS_DIR
- 前端新增 skills/ specialists/ connectors/ xapps/ 目录与对应页面

验证:前端 npm run build 通过(7.26s)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-19 01:23:51 +08:00
eaiadminandClaude Code ddd2d2cbd8 docs: 对象命名规范 AR09 与标准化讨论文档入库
- 新增 docs/02_Architecture/AR09_Object_Naming_Standard.md(规范性文件,非设计稿):
  十节结构 —— 原理 / 判据 / 对象术语表 / 五层命名规范 / 命名模式库 /
  如何检查(人工五问 + 6 个机器守卫)/ 如何修复(迁移顺序 + 改名六步法)/
  现状问题登记(逐条带 file:line)/ 反例库 / 修订记录。
  核心判断:名称即契约,改名前先查已靠名字建立的协议表
- 02_Architecture/README.md 登记 AR09,并说明其规范性定位(约束新增代码,
  与 TOP_CODING_RULES.md 的 G03 配套),与 AR01–AR08 设计稿区别
- 收入本轮讨论与调研文档:对象命名标准化清单、对象标准化与解耦总则、
  六层架构与三对象建设重点阶段性复盘、目录结构化迁移说明、
  AionUi 对照分析两篇

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-17 23:38:42 +08:00
eaiadminandClaude Code d0d7b3588c refactor: 对象命名标准化落地(RoleKind→ObjectKind、capability/assistant 收口)
后端
- model.SkillDefinition.RoleKind 改名 ObjectKind(列 role_kind → object_kind);
  新增 migrateSkillObjectKindColumn:先拷数据再显式 drop 旧列。
  GORM AutoMigrate 只加不删,字段改名不手写迁移就会新旧两列并存。
- Specialist 结构化列更名走同一套 migrateColumnData:
  role_card_json → interaction_card_json、source_records_json → inputs_records_json
- api/capability_definition.go(413 行)拆为 skill_action_definition.go,
  不再让 capability 充当一级对象名;该文件同时承载技能与动作定义处理器
- 新增 model/app_definition.go + api/app_definition.go:应用目录定义正式建模
- SkillDefinition 移除已废弃的 LegacyObjectEntryRoute 字段,对应迁移分支一并删除
- skill_keys.go 注释更新:权威来源为前端 staticSkillCatalog

前端
- api/assistant.js → chat.js、api/capability.js → skill.js,新增 api/appDefinition.js
- 新增 store/specialistCatalog.js、skillCatalog.js、appCatalog.js,
  取代 config/productizedApps.js(已删)
- config/workbench.js 静态目录去失真:businessApps → staticSpecialistCatalog
  (该变量装的其实是专员目录,与应用 app 语义直接冲突)、
  availableSkills → staticSkillCatalog
- 修复入口 query 协议断裂:写端 appCatalog 用 app_specialist/app_skill/app_prompt,
  读端 SmartAssistantPage 读同名参数并挂响应式监听。
  此前写读两侧命名不一致且无人读旧名,导致从应用目录打开应用时
  预置专员/技能/提示词被静默丢弃、无任何报错
- 页面与组件局部变量去失真:拿到专员对象不再命名为 app

验证:CGO_ENABLED=0 go build ./... 通过;go test ./... 全包通过;npm run build 通过。
旧变量名 businessApps / availableSkills / productizedApps / api/capability / api/assistant
全仓 grep 无残留。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-17 23:38:40 +08:00
eaiadminandClaude Code 6194c4733e docs: CODING_RULES 更名为 TOP_CODING_RULES 并补齐通用规则与踩坑清单
改名(对齐 pj0034 的 TOP_ 前缀):
- CODING_RULES.md → TOP_CODING_RULES.md,同步 5 处引用
  (CLAUDE.md 目录树与启动仪式、PROJECT_STATE.md 三处、DR03、DR04、文件内 G06 自引用)

补齐通用部分 G09–G18(承接 pj0034 同名文件的通用规则,按本项目
Go / Vue3 / SQLite / Ubuntu 技术栈改写):
- G09 登录态与接口必须无状态化
- G10 配置化优先,禁止写死环境细节
- G11 素材必须可追溯,不可静默修改
- G12 长耗时任务必须异步化
- G13 先跑通主线,再细化和优化
- G14 Git 不抢戏 — 收工时统一提示一次
- G15 禁止通用名启动入口文件,启动逻辑必须在 start_dev_10231_10232.sh
- G16 Windows 侧 .ps1 脚本统一 UTF-8 with BOM
- G17 脚本内禁止兼容式依赖回退,必须固定单一工具链
- G18 仓库应尽量支持拷贝后直接运行
不抄的(逐条判断本项目不适用):Python 虚拟环境、Playwright/clickflow E2E、
OSS 多租户、Amazon 平台规范检测;该判断已写进文件头说明。

G04 补第 6–10 条:全绿≠跑通、报告事实而非意图、读清用户的 bug 描述、
修 UI bug 追完整渲染链、跨区移动数据后验另一端完整性。

新增 P06 常见技术陷阱清单(11 条,全部来自本项目真实事故或核过代码的事实):
AutoMigrate 只加不删、探测脚本用完即删、worker_run.status 恒为 done、
seed 只补空字段、禁止按进程名模糊匹配杀进程、Element Plus persistent
留隐藏 DOM、动用户数据前先备份再列清单、hash 路由改 hash 不重载、
gofmt 不要整个目录 -w、git remote 禁嵌明文凭据、禁引第三方受限素材。

顺手修三处不一致:P01 索引名过时(培训平台→通用数字员工平台)、
DR03 引用的编号在重组后指向了错规则(第 6 条→G07)、第二部分标题层级。

版号 V1.0 → V1.1。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-17 22:59:17 +08:00
eaiadminandClaude Code 16d63de4e1 chore: 工作台产品化进行中的改动
把工作区里其余在制品一并入库,主要是工作台产品化的推进:

  后端:新增 capability_definition / project / my_app_center / office_skill
        接口与 action_definition / skill_definition / project / user_app_center
        模型,config 加路由健康上报。
  前端:新增 frontend/src/skills(Office 技能与 workbuddy 复刻)、
        项目管理、应用中心、能力目录页,以及配套 api / store / config;
        聊天侧新增 SpecialistChip / SpecialistPanel / SkillStrip / AppChatRail
        等组件。
  清理:移除旧 views/tools 下的单页工具(已并入工作台)、_frozen 冻结组件、
        cmd/inspect_oa_debug 调试入口,以及两份调试笔记。
  其它:文档与启动脚本同步。

(这批改动与上一提交的 SY23 工作并行进行,此前已在同一工作区内交织。)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-17 21:32:35 +08:00
eaiadminandClaude Code 8b136d4a10 feat: 专员岗位说明书与技能绑定打通(SY23 P0–P4)
工作台对话此前根本不读专员表:smart_assistant.go 里两条写死的 prompt,
专员表零参与,所以「选哪个专员说话都一样」。本次把
「专员 → 岗位说明书 → 技能」接进 system prompt。

P0 修 bug
  batch/extract 与 contract/review 直接把 nil 当路由传给 AI 层,
  取 primary.RouteID 时空指针,这两个接口必 500。
  llm.go 抽出 buildRouteChain,nil 主路由改为显式报错。

P1 数据层
  specialist 表加 rule_file_markdown(岗位说明书正文)与 allowed_skills
  (绑定技能,顺序即优先级)。写入侧用 model.ValidSkillKeys 校验,
  非法 key / 重复项直接 400,并规范化成紧凑 JSON 落库。
  播种 11 份岗位说明书初稿与技能绑定,沿用「存在则只补空字段」,
  管理员改过的内容不会被重启覆盖。

P2 打通链路
  请求体加 task_id 与 specialist_key。后端按任务反查专员(专员是任务的
  字段,任务优先),查不到安静退回通用助手而不是报错打断对话。
  ai_call_log 加 specialist_key,用来回答「这条回答是谁说的」。

P3 注入 prompt
  system prompt 改为 基础角色 + 【当前专员】+【可用技能】+【岗位说明书】,
  说明书放最后(离用户消息最近,优先级最高)。选了专员就不再自称
  「通用助手」——身份冲突正是老毛病的成因。

P4 前端
  对话带上当前任务与专员;专员详情页显示绑定的技能、读哪些信源、
  可以动什么。

验证
  go build / go vet / go test 全绿,45 项测试通过;前端构建通过。
  另在开发库副本上验过真实升级路径(AutoMigrate 补三列 + 播种补齐
  11 个专员),源库未被改动。
  新增防漂移测试:后端技能清单与前端 availableSkills 不一致即红灯;
  专员改名而说明书没同步也会红灯(这类静默失效最难查)。

注:llm.go / credits.go / seed.go / smart_assistant.go / api/specialist.go
同时含有并行进行中的改动(路由健康上报、清理调试埋点、技能与动作种子),
与本方案交织在同一批行内,无法单独拆出,一并随本次提交。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-17 21:32:31 +08:00
eaiadminandClaude Code fa6c26ea41 docs: 工作台设计稿收入 docs 体系,routes.go 更名 ai_routes.go
7 份散落在 frontend/src/views/workbench/ 的设计稿按现有编号体系收入 docs/,
源码目录现在只剩 12 个 .vue 页面:

  PlatformArchitectureRethink       -> docs/01_System_Overall/SY24
  WorkbenchArchitectureContract     -> docs/02_Architecture/AR05
  SkillPackagingSpecification       -> docs/02_Architecture/AR06
  ArchitectureAlignmentAudit        -> docs/02_Architecture/AR07
  RoleInteractionDesign             -> docs/02_Architecture/AR08
  YunQuParityRoadmap_OfficePlatform -> docs/06_Product_Lines/PL04
  WorkBuddySkillRpaLearning         -> docs/09_Research/RS01

14 处交叉引用同步更新(含 SY20/SY21 里指向旧源码路径的两处);三份 README 索引
补齐 SY20-SY24 与 AR05-AR08、PL04;README 顶部「本目录全是历史快照」的说法改精确
(AR05-AR08、PL04 不属于 V1.1 / V1 快照)。

AR08 文首补注「采纳与废弃」,避免它被当成现行设计照做:
- 已采纳:对象不跳页 / 不做独立工具页 / + 菜单挂载 / 切换对象=更新任务上下文
- 已废弃:「数字技术员」第三类对象(SY21 §2.2 已废除 tool 命名)、
  「通用助手 = 默认专员」、§14「与本稿冲突以本稿为准」的自我授权

backend-go: internal/api/routes.go -> ai_routes.go。该文件管的是 AI 模型路由
(LLM provider 列表),与 router.go 的 URL 路由注册同包同名易混,加文件头注释钉死。

验证:go build ./... 通过;go vet ./internal/api/ 无告警;npm run build 通过。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-17 19:26:26 +08:00
eaiadminandClaude Code 24cac4de6e chore: 交付物文件名对齐产品更名后的文档
产品更名时只改了文档没改文件,DELIVERY.md 写的是
eai_agentplatform.service / .env,磁盘上却是 eaisalestrain.*。
按文档改文件名(unit 内部路径本就是 /opt/eai_agentplatform,与之一致)。

- deploy/eaisalestrain.service -> deploy/eai_agentplatform.service
- deploy/eaisalestrain.env     -> deploy/eai_agentplatform.env
- 全仓库无任何地方引用旧文件名(仅 DR04 记录更名历史那行提到该词),不打断引用

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 17:03:19 +08:00
eaiadminandClaude Code 8ee208cc89 chore: 忽略误放的二进制与日志
eai_agentplatform/eai_agentplatform-server 这个路径是误入口:从 eai_agentplatform/
启动它,config.backendBaseDir() 取「可执行文件目录的上一级」会解析成仓库根,
于是连到另一份空库,页面看起来跟数据丢了似的(2026-09-14 踩过一轮)。
正确入口是 backend-go/bin/eai_agentplatform-server。

- 仓库根 .gitignore 加 *.log
- eai_agentplatform/.gitignore 加 eai_agentplatform-server 与 *.log,并注明原因
- 已确认 git ls-files 中无已跟踪的 .log / 同名二进制,新规则不误伤

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 17:01:18 +08:00
eaiadminandClaude Code 20df2ff06e feat: SQLite 定期备份内置进二进制
SQLite 是单文件、没有外部主从,坏一份就是全丢,而 data/ 一直被 gitignore、
此前没有任何备份。备份做进二进制,不依赖外部 cron / systemd timer。

- 快照用 VACUUM INTO,不用 cp 主库:服务边跑边写时 cp 可能拷到写了一半的页
- 启动时补一次,之后每小时醒一次看是否到期;默认间隔 24h、保留最近 7 份
- 产出自检 SQLite 文件头,不合格即删并报错,不留「看着像备份的废物」
- 新增 -backup 子命令,供升级 / 迁移 / 交付前手工备一份
- 落 data/backups/ —— systemd 单元是 ProtectSystem=strict,只放开了 data/ 可写
- 边界写进文档:只防误删 / 误改 / 写坏,不防整盘损坏,跨机保存仍需人工

配套:
- deploy/DELIVERY.md 新增第 7 节「数据备份与恢复」+ 红线条目
- clonezilla-cleanup.sh 提示克隆前清空 data/backups/,避免原型机测试数据被带走
- deploy/eaisalestrain.env 补 4 个备份环境变量
- PROJECT_STATE.md 记 D24

另:清理 worker_task 中 17 条没聊过天的历史空任务(id 1-11、13-18),
删前先备份、清单经确认,删除程序带「命中数与白名单不一致即中止」保险。
该项为一次性数据操作,不产生代码改动。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 16:33:05 +08:00
eaiadminandClaude Code f197dbd206 feat: 工作台外壳收尾 + 冻结旧导航 + 任务延迟创建与最近任务行菜单
外壳收尾
- 后端:内置「通用智能助手」(specialist.state = system)—— 它是任务的默认归属,
  不是可安装的专员,常规列表一律挡掉,只有显式带 state=system 才查得到
- config/nav.js:一级导航、二级 tab、搜索面板共用一份配置,替代原先散在 layout/ 与
  config/workbench.js 里的两套,旧的那批导航导出随之下架
- NavSearch.vue / SectionTabs.vue 组件化;考试 8 个页面收进 ExamTabsView 统一外壳
- 新增 /apps 专员选择页(SpecialistPickerPage.vue)
- ChatInputBar 重构:输入框的 + 拆为独立组件 PlusMenu.vue,新增 update:mode 事件
- 删除 LibraryTabs.vue(已被 SectionTabs 取代)

冻结旧导航(新增 frontend/src/_frozen/ + FROZEN.md 登记表)
- 工作区胶囊条连通知铃铛一起冻:外壳重构后成了冗余的第二套导航。不删代码,
  抽成自包含的 WorkspaceTabs.frozen.vue 归档,将来能原样放回
- 同源孤儿一并收拢:旧 SideNav / SectionTabs / navigation.js / Notification.vue
- 统一加 .frozen 后缀,登记表逐条写明原位置 / 冻结原因 / 外部依赖 / 解冻条件 / 解冻步骤
- 已验:冻结物不进构建产物(dist 里搜不到 wb-tabs),src/ 下无代码引用,
  只有 MainLayout 里指向 FROZEN.md 的指引注释
- 后端通知四接口与 store/api 层保留(BusinessAppPage 仍在用),解冻是纯前端工作量

我的任务
- 任务记录延迟到发出第一条消息时创建:新建任务只回到开场画布,不落库,
  标题取第一句话,专员取输入框 + 里先选的那个(pendingSpecialistKey 暂存,
  建任务时一并提交)。原实现点一次落一条「新任务」,是「最近任务」堆满空行的根因
- 最近任务行菜单:重命名(就地编辑,回车提交 / Esc 取消)、置顶、删除
  (硬删无回收站,确认框写明无法恢复)。新增 worker_task.pinned 字段、
  DELETE /api/worker/my-tasks/:id,列表排序改为 pinned DESC, updated_at DESC;
  el-dropdown 加 :persistent="false"(默认每行留一份隐藏菜单在 DOM 里)
- 对照 ChatGPT / WorkBuddy 后决定不做:分享任务(纯内网)、打开文件夹(Web 无此能力)、
  保存到工作空间(无 workspace 概念)、归档(没有「已归档」入口可找回)
- 当前任务高亮改用 WorkBuddy 绿;空列表给出「发送第一条消息后出现在这里」提示
- PROJECT_STATE.md 补记 D21(冻结机制)/ D22(延迟建任务)/ D23(行菜单)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 16:19:18 +08:00
eaiadminandClaude Code 5c3d5987d9 style: 智能助手最佳实践卡片收窄,固定一行 3 张
- .best-practices 增加 max-width: 480px(原撑满 720px 容器),
  卡片宽度 ~232px → ~152px;标题行共用该宽度以与卡片边缘对齐
- 移除 1200px / 768px 两处列数折叠,任何视口宽度下卡片均保持一行 3 张;
  变窄时收缩 480px 上限而非减少列数,避免第三张换到第二行
- 列宽改为 minmax(0, 1fr),防止内容撑破列宽
- .card-meta 增加省略号截断,避免窄屏下溢出卡片

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 08:25:16 +08:00
eaiadminandClaude Code 95fcf161b0 feat: 工作台外壳重构 + /home 改为智能助手 + 产品更名
前端
- MainLayout: 移除顶部标题栏,Workspace Tabs 提至最顶层,通知铃随行
- 账号入口由右上角移至左下角侧边栏底部(下拉:我的资料 / 退出登录),
  折叠态仅保留头像
- /home 现渲染智能助手并作为其规范 URL;/tools/smart-assistant 保留为重定向别名
- 工作台总览移至 /overview,侧边栏入口同步调整
- workbench store: 新增 tab 归一化,迁移已持久化的旧标签与旧路由
- 智能助手欢迎语改为「我 Bosheng 数字员工,我帮你」
- 最佳实践卡片: 4 张减为 3 张,图片块高度减半(aspect-ratio 4/3 → 8/3)

产品更名
- 后端 system prompt、CLAUDE.md、PROJECT_STATE.md 及设计文档:
  博昇内部培训平台 → EAI 数字员工平台

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 08:19:42 +08:00
eaiadminandClaude Code 5c0870af97 feat: AI Tools 统一聊天优先界面重构 — WorkBuddy 风格
Phase 1: 共享组件 + 全页面转换

共享组件 (5 个):
- ChatLayout.vue: 主布局外壳,左侧任务栏 + 聊天区域 + 底部输入栏
- ChatInputBar.vue: 统一输入框,支持文件/语音/引用附件,自动高度
- ChatMessage.vue: 消息气泡,支持用户/AI/任务计划/文件/结构化数据
- HistorySidebar.vue: 对话历史侧边栏,按时间分组,支持搜索/重命名/删除
- FileAttachment.vue: 文件上传组件,拖放/点击,支持多类型

页面转换 (6 个):
- SmartAssistantPage: 对话/任务拆解/文案生成/批量提取模式
- DocumentTranslatePage: 翻译配置面板 + 翻译结果卡片
- AudioTranscribePage: 音频转录 + 识别结果展示
- CopyProofreadingPage: 校对配置 + 问题列表 + 评分条
- BatchExtractPage: 字段提取 + 表格结果
- ContractReviewPage: 审查配置 + 评分环 + 风险等级列表

布局特点:
- 顶部分类 pill (文档处理/金融服务/数据分析/个人工作台/幻灯片)
- 居中输入框,大尺寸,拖放文件
- 最佳实践推荐卡片
- 左侧任务栏 (助理/项目/专家/定时任务/资料库)
- 消息列表 + 底部输入 (聊天模式)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 01:44:12 +08:00
eaiadmin 9de09dfa72 Merge branch 'main' of gitea: keep local product name eai_agentplatform_app
Resolved conflict in docs/微趣MyGPT调研与办公智能体架构对比.md:
kept HEAD (local) product name eai_agentplatform_app over remote eaisalestrain_app
2026-09-14 01:03:29 +08:00
eaiadminandClaude Code 0455f064ac feat: 新增语音转文字(ASR)功能
- 后端:新增 /api/audio/transcribe 接口,调用 Ollama whisper 进行语音识别
- 前端:新增 AudioTranscribePage.vue 页面,支持 MP3/WAV/M4A/OGG/FLAC 等格式
- 注册路由、工具卡片、智能助手欢迎语更新

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 00:53:36 +08:00
eaiadmin b61db6684e docs: 新增 MyGPT 调研与办公智能体架构对比 2026-09-13 23:46:39 +08:00
eaiadminandClaude Code 752c7837ef feat: 新增合同审查功能 —— AI 条款完整性检查 + 风险评分 + 修改建议
- 后端:contract_review.go —— 检查条款完整性、付款/违约/争议条款、风险评分 0-100、AI 深度审查
- 前端:ContractReviewPage.vue —— 合同输入、风险评分展示、风险详情列表、修改建议
- 路由:POST /api/contract/review + 前端 /tools/contract-review 路由
- 模板:StudioPage 新增合同审查模板入口

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-13 23:27:08 +08:00
eaiadminandClaude Code 3c58b376b3 feat: 新增文档翻译 + 文案校对 + 智能助手 + 批量字段提取四大功能
- 文档翻译:多语言翻译(中英日韩法德西),支持导出 Word/PPT/Excel/PDF
- 文案校对:错别字/语病/风格/数据检查,三级校对模式,质量评分
- 智能助手:对话/任务拆解/文案生成/批量提取 四个模式入口
- 批量提取:自定义字段配置,AI 结构化提取,CSV 导出

后端新增 API:/api/document/translate /api/copy/proofread /api/assistant/chat /api/batch/extract
前端新增页面:4 个新页面 + 模板入口 + API 模块
路由更新:tools/ 系列页面路由

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-13 22:56:40 +08:00
eaiadmin 8d849ab4d9 feat: 报告生成页面完善 - 多格式导出下拉菜单 + 描述更新
- 报告生成页面增加多格式导出下拉菜单(PDF/Word/PPT/Excel)
- 更新页面描述和 StudioPage 模板定义
- 导出按格式名提示成功/失败信息
2026-09-13 22:09:57 +08:00
eaiadmin 8c33dde2d6 feat: 报告生成扩展 PPT/Word/Excel 多格式导出
- 新增 ExportReportDOCX 导出 Word 文档(纯标准库)
- 新增 ExportReportPPTX 导出 PPT 演示文稿(纯标准库)
- 新增 ExportReportXLSX 导出 Excel 表格(纯标准库)
- 新增 /api/report/export/{docx,pptx,xlsx} 路由
- 前端增加多格式导出下拉菜单(PDF/Word/PPT/Excel)
- 前端导出函数按格式名提示成功信息
- 零网络依赖,纯 Go 标准库实现
2026-09-13 22:09:19 +08:00
eaiadminandClaude Code c8781bfe90 feat: 报告生成模块(LLM 生成 + PDF 导出 + 前端页面)
- 新增报告生成 API(/api/report/generate, /api/report/export/pdf, /api/report/preview)
- 新增 PDF 导出模块(gofpdf,支持系统中文字体自动检测)
- 新增前端报告生成页面(report/ReportGenerationPage.vue)
- 新增前端 API(report.js)
- 路由注册(后端 router.go + 前端 router/index.js)
- Studio 页面新增「报告生成」应用入口

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-13 19:38:44 +08:00
Jackzhou bd7fe63b70 完善训练模块 2026-09-04 17:02:05 +08:00
Jackzhou 8dfcb6547c 公众号助手bug修复 2026-08-27 18:00:58 +08:00
Jackzhou f864cc2c87 公众号助手新增图片 2026-08-26 17:34:21 +08:00
Jackzhou b00e55f0e5 添加公众号助手 2026-08-26 10:35:46 +08:00
Jackzhou 4f33b036d1 feat: 同步知识库与工作台相关改动 2026-08-24 10:40:15 +08:00
eaiadmin 8d0588827d add: 纳入培训素材、产品介绍 PPT、微信研究图片到版本管理 2026-08-18 20:24:48 +08:00
eaiadmin 4e8817d768 init: 数字员工平台初始代码
包含前端(Vue3 + VueFlow 画布)、后端(Go)、文档体系。
- 工作台画布:节点拖放、连线模式、右键菜单、AI 助手
- 后端:连接器 API、专员种子数据
- 导航:左侧导航、工坊、市场、控制台
2026-08-18 20:19:58 +08:00