Files
prop-ai-hr/docs/superpowers/plans/2026-07-24-digital-master-agent.md
T

18 KiB
Raw Blame History

数字师傅工作 Agent Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 将移动端“问”从默认 RAG 查询改为受身份、权限、确认和审计约束的数字师傅工作 Agent,并保持现有知识、数据工具、记忆、全网和媒体链路兼容。

Architecture: 新增 org.dromara.aihr.agent 编排边界,Planner 只产生受校验的意图和工具计划,Policy 固定角色与工具许可,Orchestrator 复用现有领域服务。旧 /api/knowledge/** 与 /api/aihr/web-ai/** 保留;移动端改用 /api/aihr/agent/** 的统一响应,不从模型自由文本决定按钮或业务状态。

Tech Stack: Java 17、Spring Boot、Sa-Token、JdbcTemplate、Jackson、JUnit 5/Mockito、uni-app Vue 3/TypeScript、Node test、MySQL 8。

实施状态(2026-07-24): Tasks 1–8 及 Task 9 的自动化、H5 构建和当前事实文档已完成;后端相关回归 91/91、移动端 Agent 契约 3/3。390×844 浏览器已验证寒暄、训练实时来源、全网同意和普通媒体分析;确认式写入、现场风险图 + SOP、旧资源撤权,以及主管/候选人入口仍未完成正式账号/真机浏览器验收。本分支尚未部署或生产验证。


Scope split

本计划完整实现已确认的 Agent 设计。课程播放器/防快进和个人文件/网页知识空间有独立数据生命周期,不塞入 Agent 编排改动;Agent 只读取当前已经正式存在的学习、训练、工作成果、记忆和知识能力。它们分别形成后续独立计划,不影响本计划验收。

Task 1: Agent contract and conservative planner

Files:

  • Create: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentDto.java

  • Create: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentPlanner.java

  • Test: backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentPlannerTest.java

  • Step 1: Write failing planner tests

Cover exact routes:

assertEquals(Intent.LIVE_MY_WORK, planner.plan("我今天有什么待办", false).intent());
assertEquals(Tool.MY_CURRENT_TASKS, planner.plan("我今天有什么待办", false).tool());
assertEquals(Intent.CAPTURE_FACT, planner.plan("记一下,3栋1201要回访", false).intent());
assertEquals(Intent.SOCIAL, planner.plan("你好", false).intent());
assertEquals(Intent.CLARIFY, planner.plan("帮我处理一下", false).intent());
assertEquals(Intent.MEDIA_UNDERSTANDING, planner.plan("图中是什么宠物", true).intent());
assertEquals(Intent.KNOWLEDGE_QA, planner.plan("装修人员怎么进场", false).intent());
  • Step 2: Run the focused test and verify RED

Run:

timeout 120s mvn -pl ruoyi-modules/ruoyi-aihr -am \
  -DskipTests=false -Dsurefire.failIfNoSpecifiedTests=false \
  -Dtest=AihrAgentPlannerTest test

Expected: compilation failure because Agent contract and planner do not exist.

  • Step 3: Add the minimal typed contract

AihrAgentDto defines:

enum Intent {
    KNOWLEDGE_QA, RESOURCE_DELIVERY, LIVE_MY_WORK, LIVE_TEAM_WORK,
    PRACTICE_COACHING, CAPTURE_FACT, DRAFT_ACTION,
    MEDIA_UNDERSTANDING, WEB_RESEARCH, CLARIFY, SOCIAL
}

enum Tool {
    NONE, KNOWLEDGE_SEARCH, KNOWLEDGE_RESOURCE, MY_CURRENT_TASKS,
    MY_PRACTICE_SUMMARY, TEAM_PRACTICE_SUMMARY,
    CAPTURE_MEMORY_DRAFT, MEDIA_ANALYZE, WEB_RESEARCH
}

record AgentPlan(
    Intent intent,
    String rewrittenRequest,
    Tool tool,
    boolean requiresConfirmation,
    boolean requiresExternalConsent,
    ResponseStyle responseStyle
) {}

Add request/response records matching the approved design. Requests accept question, conversation/version, project, broadcast ID and explicit external consent; they do not accept identity, role or tool name.

  • Step 4: Implement deterministic safe routing, then optional model refinement

Known high-confidence intents route deterministically. Model output is parsed only when it matches known enums, contains at most one tool and does not supply identity/project IDs. Invalid or unavailable model output returns deterministic CLARIFY, never default RAG.

  • Step 5: Run planner tests and commit

Expected: all AihrAgentPlannerTest tests pass.

git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent \
  backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentPlannerTest.java
git commit -m "feat(agent): add conservative intent planner"

Task 2: Policy gate and registered tool metadata

Files:

  • Create: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentPolicy.java

  • Test: backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentPolicyTest.java

  • Step 1: Write failing policy tests

Required assertions:

assertDoesNotThrow(() -> policy.authorize(employee, plan(MY_CURRENT_TASKS)));
assertThrows(ServiceException.class, () -> policy.authorize(employee, plan(TEAM_PRACTICE_SUMMARY)));
assertDoesNotThrow(() -> policy.authorize(supervisor, plan(TEAM_PRACTICE_SUMMARY)));
assertThrows(ServiceException.class, () -> policy.authorize(candidate, plan(MY_CURRENT_TASKS)));
assertThrows(ServiceException.class, () -> policy.authorize(employee, forgedUnknownToolPlan));
  • Step 2: Verify RED

Run AihrAgentPolicyTest with the same Maven command pattern.

  • Step 3: Implement one explicit switch

AihrAgentPolicy declares risk and allowed roles for each Tool; it rejects unsupported role/tool pairs, write-like plans without confirmation, external plans without consent and multiple calls. Do not introduce an interface/factory/registry framework.

  • Step 4: Verify GREEN and commit
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentPolicy.java \
  backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentPolicyTest.java
git commit -m "feat(agent): enforce tool policy"

Task 3: Read-only orchestrator and unified API

Files:

  • Create: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentOrchestrator.java

  • Create: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentController.java

  • Test: backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentOrchestratorTest.java

  • Test: backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentControllerContractTest.java

  • Step 1: Write failing orchestrator tests

Verify:

  • LIVE_MY_WORK sends only MY_CURRENT_TASKS to the existing query/data-tool chain and never invokes RAG.

  • KNOWLEDGE_QA delegates to AihrKnowledgeQueryService.

  • SOCIAL and CLARIFY do not invoke knowledge or data services.

  • unavailable data maps to UNAVAILABLE; no task maps to COMPLETED plus data.state=NO_TASKS.

  • the controller has login protection and does not expose identity/tool parameters.

  • Step 2: Verify RED

Run:

timeout 120s mvn -pl ruoyi-modules/ruoyi-aihr -am \
  -DskipTests=false -Dsurefire.failIfNoSpecifiedTests=false \
  -Dtest=AihrAgentOrchestratorTest,AihrAgentControllerContractTest test
  • Step 3: Implement the unified text endpoint

Add:

POST /api/aihr/agent/messages

The orchestrator resolves the current principal server-side, calls Planner, then Policy, and delegates to existing services. It maps citations, resources, conversation/version and data into AgentResponse.

  • Step 4: Verify GREEN and commit
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent \
  backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent
git commit -m "feat(agent): orchestrate read-only work tools"

Task 4: Correct media routing and conversation context

Files:

  • Modify: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/knowledge/service/AihrKnowledgeQueryService.java

  • Modify: backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/knowledge/AihrKnowledgeQueryServiceTest.java

  • Modify: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentOrchestrator.java

  • Modify: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentController.java

  • Test: backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentMediaTest.java

  • Step 1: Write failing tests for both media modes

Verify:

  • “图中是什么宠物” returns the vision observation, labels it MEDIA, does not call SOP search and appends that answer to the short conversation.

  • “图中电梯门打不开怎么办” may combine vision context with authorized SOP search.

  • no-evidence work media still returns the vision observation and explicitly marks missing SOP evidence.

  • Step 2: Verify RED

Run focused knowledge and Agent media tests.

  • Step 3: Expose one internal media mode

Change the knowledge media method to accept an internal enum MEDIA_ONLY|MEDIA_WITH_KNOWLEDGE; the client cannot submit it. Reuse current extraction, authorization, size checks and conversation append. MEDIA_ONLY skips queryDocuments.

  • Step 4: Add the multipart Agent endpoint

Add:

POST /api/aihr/agent/messages/media

Request parameters mirror text conversation/project fields and explicit consent only.

  • Step 5: Verify GREEN and commit
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent \
  backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/knowledge/service/AihrKnowledgeQueryService.java \
  backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr
git commit -m "fix(agent): route media by intent"

Task 5: Confirmation actions by reference, not duplicate business logic

Files:

  • Create: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentActionService.java

  • Modify: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentController.java

  • Test: backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentActionServiceTest.java

  • Step 1: Write failing capture-action tests

Verify:

  • capture intent creates/reuses the existing memory candidate and returns NEEDS_CONFIRMATION;

  • confirmation requires candidate version, idempotency key, edited draft and PRIVATE|COMPANY;

  • duplicate identical confirmation returns the same target;

  • changed payload with the same key, expired candidate and cross-user candidate are rejected;

  • dismiss delegates to the existing candidate state machine.

  • Step 2: Verify RED

Run AihrAgentActionServiceTest.

  • Step 3: Implement reference-backed actions

Agent draftId is opaque and resolves server-side to an existing domain draft. Confirmation delegates to AihrMemoryService.confirm; dismissal delegates to AihrMemoryService.dismiss. Do not duplicate memory normalization, authorization, persistence or idempotency logic.

  • Step 4: Add endpoints and verify GREEN
POST /api/aihr/agent/actions/{draftId}/confirm
POST /api/aihr/agent/actions/{draftId}/dismiss
  • Step 5: Commit
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent \
  backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent
git commit -m "feat(agent): confirm existing domain drafts"

Files:

  • Modify: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentOrchestrator.java

  • Test: backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentWebResearchTest.java

  • Step 1: Write failing consent tests

Without consent, WEB_RESEARCH returns a clarification/consent card and never calls AihrWebAiService. With consent, it delegates to the existing web service and maps only web sources; enterprise citations stay empty.

  • Step 2: Verify RED, implement minimal delegation, verify GREEN

Keep existing provider enablement, HTTPS validation, privacy redaction and rate limits inside AihrWebAiService.

  • Step 3: Commit
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentOrchestrator.java \
  backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentWebResearchTest.java
git commit -m "feat(agent): require web research consent"

Task 7: Minimal Agent audit and migration

Files:

  • Create: backend/script/sql/update/aihr_20260724_agent_orchestration_mysql8.sql

  • Modify: backend/script/sql/aihr_knowledge_mysql8.sql

  • Create: backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentAuditService.java

  • Modify: scripts/reset-dev-db.sh

  • Modify: scripts/release-preflight.sh

  • Modify: scripts/tests/aihr-schema-migrations.test.sh

  • Test: backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent/AihrAgentAuditServiceTest.java

  • Step 1: Write failing schema and audit tests

Assert the migration provides aihr_agent_run with run, tenant/app/user, conversation/version, intent, tool, status, source type, duration and sanitized error code. Action details remain in existing domain draft tables and are linked by result_ref; do not duplicate sensitive request bodies.

  • Step 2: Verify RED

Run Java audit test plus:

bash scripts/tests/aihr-schema-migrations.test.sh
  • Step 3: Add idempotent MySQL migration and audit writer

The service records final state in a finally-safe path. Audit failure logs a sanitized warning and does not turn a valid user response into failure.

  • Step 4: Extend reset and read-only preflight checks

Production request code must not run DDL. Preflight checks the table and required indexes.

  • Step 5: Verify GREEN and commit
git add backend/script/sql backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent \
  backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/agent \
  scripts/reset-dev-db.sh scripts/release-preflight.sh scripts/tests/aihr-schema-migrations.test.sh
git commit -m "feat(agent): audit orchestrated runs"

Task 8: Move mobile “问” to the Agent response contract

Files:

  • Create: mobile-uni/src/services/agent.ts

  • Modify: mobile-uni/src/types/api.ts

  • Modify: mobile-uni/src/pages/user/sop/index.vue

  • Test: mobile-uni/tests/agent.test.mjs

  • Test: mobile-uni/tests/mobile-user-pages.test.mjs

  • Step 1: Write failing contract tests

Verify source chips, NO_EVIDENCE/UNAVAILABLE/FORBIDDEN, clarification cards, memory confirmation cards, external-consent prompts, citations/resources and media uploads all use the new Agent endpoints. Verify the UI never derives an action button from answer text.

  • Step 2: Verify RED

Run:

node --test mobile-uni/tests/agent.test.mjs mobile-uni/tests/mobile-user-pages.test.mjs
  • Step 3: Add typed Agent service and map the existing chat page

Reuse existing audio recording, upload, citation, resource, memory-card and conversation-version UI. Add only source chips, clarification/consent card and status-specific copy. Keep legacy knowledge service for compatibility outside this page.

  • Step 4: Verify tests and H5 build
node --test mobile-uni/tests/agent.test.mjs mobile-uni/tests/mobile-user-pages.test.mjs
npm --prefix mobile-uni run build:h5
  • Step 5: Commit
git add mobile-uni/src/services/agent.ts mobile-uni/src/types/api.ts \
  mobile-uni/src/pages/user/sop/index.vue mobile-uni/tests
git commit -m "feat(mobile): use digital master agent"

Task 9: Regression, docs, browser and release handoff

Files:

  • Modify: docs/API_INTEGRATION.md

  • Modify: docs/BRD_IMPLEMENTATION_AUDIT.md

  • Modify: docs/20260708/数字师傅学练问报整合方案.md

  • Modify: docs/superpowers/specs/2026-07-24-digital-master-agent-design.md

  • Step 1: Run backend regression

timeout 120s mvn -pl ruoyi-modules/ruoyi-aihr -am \
  -DskipTests=false -Dsurefire.failIfNoSpecifiedTests=false \
  -Dtest='AihrAgent*Test,AihrKnowledgeQueryServiceTest,AihrKnowledgeDataToolServiceTest,AihrMemoryServiceTest' test
  • Step 2: Run mobile regression and build
node --test mobile-uni/tests/*.test.mjs
npm --prefix mobile-uni run build:h5
git diff --check
  • Step 3: Update current-truth documentation

Document exact API contract, migration order, implemented/verified/deployed distinction and remaining courseware/personal-resource subprojects. Remove “待评审” from the approved design.

  • Step 4: Complete authenticated browser and real-device acceptance

已在 390×844 完成寒暄、训练实时来源、全网同意和普通媒体分析。发布前仍须以正式账号/真机补齐:

  1. “记一下,3栋1201要回访” — confirmation before persistence.
  2. work-risk image — media + authorized SOP or explicit no evidence.
  3. old file follow-up — protected resource delivery and revoked-access rejection.

同时补齐桌面宽度、键盘、焦点、确认/撤销反馈和主管/候选人角色正反例;截图不能替代实际交互。

  • Step 5: Prepare the final documentation commit and preserve the release gate
git add docs
git commit -m "docs(agent): record implementation and acceptance"

本次只提交本地实现和事实文档。未执行发布;只有在干净已提交树上完成远端静态、后端、schema 三项预检并补齐上面的正式验收,才可更新为 deployed / production-verified。