docs(agent): sync final implementation state

This commit is contained in:
2026-07-25 00:03:19 +08:00
parent 9b39ffbb76
commit a67444645e
10 changed files with 157 additions and 105 deletions
@@ -8,6 +8,8 @@
**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
@@ -21,7 +23,7 @@
- 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**
- [x] **Step 1: Write failing planner tests**
Cover exact routes:
@@ -35,7 +37,7 @@ assertEquals(Intent.MEDIA_UNDERSTANDING, planner.plan("图中是什么宠物", t
assertEquals(Intent.KNOWLEDGE_QA, planner.plan("装修人员怎么进场", false).intent());
```
- [ ] **Step 2: Run the focused test and verify RED**
- [x] **Step 2: Run the focused test and verify RED**
Run:
@@ -47,7 +49,7 @@ timeout 120s mvn -pl ruoyi-modules/ruoyi-aihr -am \
Expected: compilation failure because Agent contract and planner do not exist.
- [ ] **Step 3: Add the minimal typed contract**
- [x] **Step 3: Add the minimal typed contract**
`AihrAgentDto` defines:
@@ -76,11 +78,11 @@ record AgentPlan(
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**
- [x] **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**
- [x] **Step 5: Run planner tests and commit**
Expected: all `AihrAgentPlannerTest` tests pass.
@@ -96,7 +98,7 @@ git commit -m "feat(agent): add conservative intent planner"
- 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**
- [x] **Step 1: Write failing policy tests**
Required assertions:
@@ -108,15 +110,15 @@ assertThrows(ServiceException.class, () -> policy.authorize(candidate, plan(MY_C
assertThrows(ServiceException.class, () -> policy.authorize(employee, forgedUnknownToolPlan));
```
- [ ] **Step 2: Verify RED**
- [x] **Step 2: Verify RED**
Run `AihrAgentPolicyTest` with the same Maven command pattern.
- [ ] **Step 3: Implement one explicit switch**
- [x] **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**
- [x] **Step 4: Verify GREEN and commit**
```bash
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentPolicy.java \
@@ -132,7 +134,7 @@ git commit -m "feat(agent): enforce tool policy"
- 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**
- [x] **Step 1: Write failing orchestrator tests**
Verify:
@@ -142,7 +144,7 @@ Verify:
- 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**
- [x] **Step 2: Verify RED**
Run:
@@ -152,7 +154,7 @@ timeout 120s mvn -pl ruoyi-modules/ruoyi-aihr -am \
-Dtest=AihrAgentOrchestratorTest,AihrAgentControllerContractTest test
```
- [ ] **Step 3: Implement the unified text endpoint**
- [x] **Step 3: Implement the unified text endpoint**
Add:
@@ -162,7 +164,7 @@ 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**
- [x] **Step 4: Verify GREEN and commit**
```bash
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent \
@@ -179,7 +181,7 @@ git commit -m "feat(agent): orchestrate read-only work tools"
- 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**
- [x] **Step 1: Write failing tests for both media modes**
Verify:
@@ -187,15 +189,15 @@ Verify:
- “图中电梯门打不开怎么办” 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**
- [x] **Step 2: Verify RED**
Run focused knowledge and Agent media tests.
- [ ] **Step 3: Expose one internal media mode**
- [x] **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**
- [x] **Step 4: Add the multipart Agent endpoint**
Add:
@@ -205,7 +207,7 @@ POST /api/aihr/agent/messages/media
Request parameters mirror text conversation/project fields and explicit consent only.
- [ ] **Step 5: Verify GREEN and commit**
- [x] **Step 5: Verify GREEN and commit**
```bash
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent \
@@ -221,7 +223,7 @@ git commit -m "fix(agent): route media by intent"
- 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**
- [x] **Step 1: Write failing capture-action tests**
Verify:
@@ -231,22 +233,22 @@ Verify:
- 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**
- [x] **Step 2: Verify RED**
Run `AihrAgentActionServiceTest`.
- [ ] **Step 3: Implement reference-backed actions**
- [x] **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**
- [x] **Step 4: Add endpoints and verify GREEN**
```text
POST /api/aihr/agent/actions/{draftId}/confirm
POST /api/aihr/agent/actions/{draftId}/dismiss
```
- [ ] **Step 5: Commit**
- [x] **Step 5: Commit**
```bash
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent \
@@ -260,15 +262,15 @@ git commit -m "feat(agent): confirm existing domain drafts"
- 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**
- [x] **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**
- [x] **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**
- [x] **Step 3: Commit**
```bash
git add backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent/AihrAgentOrchestrator.java \
@@ -287,11 +289,11 @@ git commit -m "feat(agent): require web research consent"
- 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**
- [x] **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**
- [x] **Step 2: Verify RED**
Run Java audit test plus:
@@ -299,15 +301,15 @@ Run Java audit test plus:
bash scripts/tests/aihr-schema-migrations.test.sh
```
- [ ] **Step 3: Add idempotent MySQL migration and audit writer**
- [x] **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**
- [x] **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**
- [x] **Step 5: Verify GREEN and commit**
```bash
git add backend/script/sql backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/agent \
@@ -325,11 +327,11 @@ git commit -m "feat(agent): audit orchestrated runs"
- Test: `mobile-uni/tests/agent.test.mjs`
- Test: `mobile-uni/tests/mobile-user-pages.test.mjs`
- [ ] **Step 1: Write failing contract tests**
- [x] **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**
- [x] **Step 2: Verify RED**
Run:
@@ -337,18 +339,18 @@ 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**
- [x] **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**
- [x] **Step 4: Verify tests and H5 build**
```bash
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**
- [x] **Step 5: Commit**
```bash
git add mobile-uni/src/services/agent.ts mobile-uni/src/types/api.ts \
@@ -364,7 +366,7 @@ git commit -m "feat(mobile): use digital master agent"
- Modify: `docs/20260708/数字师傅学练问报整合方案.md`
- Modify: `docs/superpowers/specs/2026-07-24-digital-master-agent-design.md`
- [ ] **Step 1: Run backend regression**
- [x] **Step 1: Run backend regression**
```bash
timeout 120s mvn -pl ruoyi-modules/ruoyi-aihr -am \
@@ -372,7 +374,7 @@ timeout 120s mvn -pl ruoyi-modules/ruoyi-aihr -am \
-Dtest='AihrAgent*Test,AihrKnowledgeQueryServiceTest,AihrKnowledgeDataToolServiceTest,AihrMemoryServiceTest' test
```
- [ ] **Step 2: Run mobile regression and build**
- [x] **Step 2: Run mobile regression and build**
```bash
node --test mobile-uni/tests/*.test.mjs
@@ -380,29 +382,25 @@ npm --prefix mobile-uni run build:h5
git diff --check
```
- [ ] **Step 3: Update current-truth documentation**
- [x] **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: Run authenticated browser acceptance**
- [ ] **Step 4: Complete authenticated browser and real-device acceptance**
At 390×844 and desktop widths, exercise:
已在 390×844 完成寒暄、训练实时来源、全网同意和普通媒体分析。发布前仍须以正式账号/真机补齐:
1. “你好” — no RAG/source card.
2. “我今天有什么待办” — live-data source and truthful `NO_TASKS|HAS_TASKS`.
3. “记一下,3栋1201要回访” — confirmation before persistence.
4. pet image — media source, no SOP lookup.
5. work-risk image — media + authorized SOP or explicit no evidence.
6. web question — consent before external call.
7. old file follow-up — protected resource delivery and revoked-access rejection.
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.
Capture screenshots and inspect layout, overflow, keyboard, focus and action-state feedback.
同时补齐桌面宽度、键盘、焦点、确认/撤销反馈和主管/候选人角色正反例;截图不能替代实际交互。
- [ ] **Step 5: Final commit and release gate**
- [x] **Step 5: Prepare the final documentation commit and preserve the release gate**
```bash
git add docs
git commit -m "docs(agent): record implementation and acceptance"
```
Do not deploy until the complete remote static/backend/schema preflight can be run from a clean committed tree. Deployment and formal production account/real-device acceptance remain separate explicit actions.
本次只提交本地实现和事实文档。未执行发布;只有在干净已提交树上完成远端静态、后端、schema 三项预检并补齐上面的正式验收,才可更新为 deployed / production-verified。