@tea-agent/loop-agent 0.33.6 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/worker/console/chat/model-resolver.js +17 -0
- package/dist/worker/console/chat/pi-runtime.js +397 -132
- package/dist/worker/console/chat/routes.js +185 -25
- package/dist/worker/console/chat/session-store.js +39 -0
- package/dist/worker/console/static/assets/index-BQkhJpV8.css +1 -0
- package/dist/worker/console/static/assets/index-CMHovlqG.js +32 -0
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/landing-density.js +23 -0
- package/dist/worker/console/static-src/operator-chat/session-title-watcher.js +128 -0
- package/dist/worker/console/static-src/operator-chat/sidebar-split.js +90 -0
- package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +37 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +109 -22
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +6 -1
- package/dist/worker/console/static-src/operator-chat/useOverlayFocus.js +84 -0
- package/dist/worker/console/static-src/operator-chat/useWorkspaceLayout.js +58 -0
- package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +31 -0
- package/harness.json +1 -1
- package/package.json +1 -1
- package/skills/local-jacoco-coverage/SKILL.md +281 -0
- package/skills/local-jacoco-coverage/references/requirement-to-source-mapping.md +85 -0
- package/skills/local-jacoco-coverage/references/runtime-alignment.md +106 -0
- package/skills/local-jacoco-coverage/scripts/run-coverage-analysis.sh +148 -0
- package/skills/local-jacoco-coverage/scripts/start-jacoco-agent.sh +110 -0
- package/dist/worker/console/static/assets/index-BUOLppPr.js +0 -28
- package/dist/worker/console/static/assets/index-C1KzazY5.css +0 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Workspace layout modes resolved from measured Chat container width. */
|
|
2
|
+
/** Width thresholds in CSS px against `.oc-workspace` (not window/UA). */
|
|
3
|
+
export const WORKSPACE_LAYOUT_THRESHOLDS = {
|
|
4
|
+
comfortableMin: 1450,
|
|
5
|
+
compactMin: 1100,
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the three-band workspace mode from a measured container width.
|
|
9
|
+
* Boundaries: comfortable >=1450, compact 1100-1449, narrow <1100.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveWorkspaceLayoutMode(widthPx) {
|
|
12
|
+
if (!Number.isFinite(widthPx) || widthPx < 0)
|
|
13
|
+
return "narrow";
|
|
14
|
+
if (widthPx >= WORKSPACE_LAYOUT_THRESHOLDS.comfortableMin)
|
|
15
|
+
return "comfortable";
|
|
16
|
+
if (widthPx >= WORKSPACE_LAYOUT_THRESHOLDS.compactMin)
|
|
17
|
+
return "compact";
|
|
18
|
+
return "narrow";
|
|
19
|
+
}
|
|
20
|
+
/** Whether process should render as a right overlay (no main reflow). */
|
|
21
|
+
export function processUsesOverlay(mode) {
|
|
22
|
+
return mode === "compact" || mode === "narrow";
|
|
23
|
+
}
|
|
24
|
+
/** Whether the permanent full sidebar is allowed. */
|
|
25
|
+
export function fullSidebarAllowed(mode) {
|
|
26
|
+
return mode === "comfortable";
|
|
27
|
+
}
|
|
28
|
+
/** Whether compact icon rail is shown. */
|
|
29
|
+
export function iconRailVisible(mode) {
|
|
30
|
+
return mode === "compact";
|
|
31
|
+
}
|
package/harness.json
CHANGED
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"pi": {
|
|
82
82
|
"description": "Pi 负责规划、评审、诊断;当 DAG toolProfile=write 时也可做有界写入。模型按复杂度三档配置,格式为 provider/model 字符串(例:wizard-local/grok-4.5);斜杠前为 Pi provider,后为 modelId,勿只写裸 modelId。",
|
|
83
83
|
"LOW": "wizard-local/minimax-m3",
|
|
84
|
-
"MED": "wizard-local/
|
|
84
|
+
"MED": "wizard-local/grok-4.5",
|
|
85
85
|
"HIGH": "wizard-local/gpt-5.6-sol"
|
|
86
86
|
}
|
|
87
87
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: local-jacoco-coverage
|
|
3
|
+
description: >-
|
|
4
|
+
本地对 Java 后端服务做代码覆盖率检测与分析的端到端编排 skill。在本地或测试环境启动后端服务并挂载 JaCoCo
|
|
5
|
+
agent(tcpserver 模式),随后用 loop-agent 的 backend-test DAG 跑后端测试,最后把 dump 出的 JaCoCo
|
|
6
|
+
报告与需求文档(PRD/AC/BR)对齐做覆盖率切片分析。用于:本地 jacoco 覆盖率、需求覆盖率分析、Java 服务覆盖率、
|
|
7
|
+
后端测试覆盖率、backend-test jacoco、本地挂 jacocoagent、覆盖率对照需求。
|
|
8
|
+
触发词:本地覆盖率检测、覆盖率分析、jacoco 覆盖率、后端代码覆盖率、需求覆盖率、挂载 jacocoagent、
|
|
9
|
+
local coverage analysis、jacoco tcpserver dump、backend-test 覆盖率分析、按需求分析覆盖率。
|
|
10
|
+
references:
|
|
11
|
+
- path: references/runtime-alignment.md
|
|
12
|
+
required: true
|
|
13
|
+
- path: references/requirement-to-source-mapping.md
|
|
14
|
+
required: true
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Local JaCoCo Coverage(本地 Java 后端覆盖率检测与分析)
|
|
18
|
+
|
|
19
|
+
本 skill 是**编排型操作手册**,不是覆盖率引擎本身。它复用 loop-agent runtime 已内置的 JaCoCo 收集与归一化能力,把"起服务挂 agent → 跑后端测试 DAG → 结合需求分析覆盖率"三件事串成一条可审计、可重复、可验证的本地链路。**禁止重造 runtime 已有的 dump/parse/归一化逻辑**;细节字段真源见 `references/runtime-alignment.md`。
|
|
20
|
+
|
|
21
|
+
## 默认立场
|
|
22
|
+
|
|
23
|
+
- 三阶段顺序强约束:**① 起服务挂 agent → ② 跑 backend-test DAG → ③ dump + 按需求切片分析**。前一阶段未拿到可验证证据前,不得进入下一阶段。
|
|
24
|
+
- JaCoCo agent 只在**测试环境**挂载;**生产环境严禁**挂载 `address=0.0.0.0` 的 tcpserver。
|
|
25
|
+
- `includes` 必须显式写**业务包名**(如 `com.yourcompany.*`);用默认 `*` 会把 Spring/Tomcat 等框架也算进去,覆盖率虚低、无参考价值。
|
|
26
|
+
- 覆盖率数据不是"通过/失败"判据,是**质量观测**。pytest 与 backend-test DAG 的执行结论以 backend-test DAG 本身的 shell verification 为准;JaCoCo 收集**全程失败安全**,任一环节出错都不阻断测试(见 `references/runtime-alignment.md` 容错表)。
|
|
27
|
+
- 需求覆盖率分析必须基于**真实的需求 ID**(`REQ-*`/`BR-*`/`AC-*`)与**真实的源码路径**;禁止凭需求文档文本臆测代码路径或编造覆盖率数字。
|
|
28
|
+
- 本 skill 不写业务代码、不修改生产配置、不写 `.env` 或 credential 文件;它只在测试环境启动 Java 服务、运行 loop-agent CLI、产出 `reports/` 与 `docs/test-reports/` 下的报告。
|
|
29
|
+
|
|
30
|
+
## 前置确认(BLOCKING)
|
|
31
|
+
|
|
32
|
+
进入 Step 1 前,必须与用户确认以下事实,缺一项则停下询问,不要猜:
|
|
33
|
+
|
|
34
|
+
| 项 | 说明 | 示例 |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| Java 服务仓库与启动方式 | 能否加 JVM 启动参数(mvn / java -jar / docker) | `mvn spring-boot:run` |
|
|
37
|
+
| 业务包名 | JaCoCo `includes` 的过滤前缀,**强烈建议显式指定** | `com.coms.bpm.*` |
|
|
38
|
+
| jacocoagent.jar 路径 | Java 服务所在机器上的 agent jar 绝对路径 | `/opt/jacoco/jacocoagent.jar` |
|
|
39
|
+
| jacococli.jar 路径 | **跑 backend-test 的机器**上的 cli jar 绝对路径(用于 `.exec → xml`) | `/opt/jacoco/jacococli.jar` |
|
|
40
|
+
| dump 端口 | tcpserver 监听端口,需与 backend-test 机器连通 | `6300` |
|
|
41
|
+
| loop-agent 控制器 | 已发布的 npm 包版本,按 AGENTS.md 记录实际版本 | `loop-agent --version` |
|
|
42
|
+
| 需求文档 | PRD / 用户故事 / AC / BR 的路径,Step 3 切片分析的输入 | `docs/product-analysis/<id>/product-requirement.md` |
|
|
43
|
+
|
|
44
|
+
确认后**回显**给用户:"分析范围:业务包 `<X>`,agent 端口 `<port>`,cli jar `<path>`,需求文档 `<path>`"。
|
|
45
|
+
|
|
46
|
+
## Step 1:本地启动后端服务并挂载 JaCoCo agent(tcpserver)
|
|
47
|
+
|
|
48
|
+
目标:让 Java 服务在测试期间把执行数据暴露成一个可被 backend-test DAG 跨网络 dump 的 tcpserver。
|
|
49
|
+
|
|
50
|
+
### 1.1 用封装脚本启动(推荐)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# <skill-root> 解析为本 SKILL.md 所在目录
|
|
54
|
+
bash <skill-root>/scripts/start-jacoco-agent.sh \
|
|
55
|
+
--agent-jar /opt/jacoco/jacocoagent.jar \
|
|
56
|
+
--includes "com.yourcompany.*" \
|
|
57
|
+
--port 6300 \
|
|
58
|
+
-- mvn spring-boot:run
|
|
59
|
+
# 或直接 java -jar:
|
|
60
|
+
# bash <skill-root>/scripts/start-jacoco-agent.sh ... -- java -jar your-app.jar
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
脚本只做三件事:校验 `--agent-jar` 存在、拼装 `-javaagent:...=output=tcpserver,address=0.0.0.0,port=<port>,includes=<pkg>,append=false`、把 `--` 之后的原始启动命令交给 exec。**它不会修改你的启动命令语义**,只前置 agent 参数。
|
|
64
|
+
|
|
65
|
+
### 1.2 等价的手工写法(脚本不可用时)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
java -javaagent:/opt/jacoco/jacocoagent.jar=output=tcpserver,address=0.0.0.0,port=6300,includes=com.yourcompany.*,append=false \
|
|
69
|
+
-jar your-app.jar
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Maven 项目:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
JACOCO_AGENT="$HOME/.m2/repository/org/jacoco/org.jacoco.agent/0.8.12/org.jacoco.agent-0.8.12-runtime.jar"
|
|
76
|
+
mvn spring-boot:run \
|
|
77
|
+
-Dspring-boot.run.jvmArguments="-javaagent:${JACOCO_AGENT}=output=tcpserver,address=0.0.0.0,port=6300,includes=com.yourcompany.*,append=false"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Docker:
|
|
81
|
+
|
|
82
|
+
```dockerfile
|
|
83
|
+
ENV JAVA_TOOL_OPTIONS="-javaagent:/opt/jacoco/jacocoagent.jar=output=tcpserver,address=0.0.0.0,port=6300,includes=com.yourcompany.*,append=false"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
docker run -p 8080:8080 -p 6300:6300 your-image
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 1.3 自检(BLOCKING,必须通过才进 Step 2)
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Java 服务进程里确实带了 jacocoagent
|
|
94
|
+
ps aux | grep -i jacocoagent | grep -v grep
|
|
95
|
+
|
|
96
|
+
# 端口对 backend-test 机器放行(在 backend-test 机器上跑)
|
|
97
|
+
nc -zv <java-service-host> 6300
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`address` 必须是 `0.0.0.0`(跨机器可达);设成 `127.0.0.1` 则 backend-test 连不上。安全组只放行 backend-test 机器。
|
|
101
|
+
|
|
102
|
+
> 字段含义、参数取值、安全约束的真源见 `references/runtime-alignment.md` 与项目 `docs/operations/backend-test-jacoco-coverage.md`。
|
|
103
|
+
|
|
104
|
+
## Step 2:启动后端测试 DAG(backend-test)
|
|
105
|
+
|
|
106
|
+
目标:让 backend-test DAG 在 Step 7(`execute-backend-pytest-and-html-report-shell`)跑完 pytest,并跨网络 dump JaCoCo 数据。backend-test DAG 是固定 9 节点 Markdown-first 工作流,真源见 `docs/runtime/backend-test-workflow.md`。
|
|
107
|
+
|
|
108
|
+
### 2.1 建任务并进 writeSet gate
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
loop-agent task advance <task-id> "后端测试 + JaCoCo 覆盖率" \
|
|
112
|
+
--task-kind backend-test \
|
|
113
|
+
--prd <需求或测试范围 PRD> \
|
|
114
|
+
--allowed-path "testcase/**" \
|
|
115
|
+
--forbidden-path ".harness/**" \
|
|
116
|
+
--verify "<label>:<项目 AGENTS.md 登记的后端测试命令>" \
|
|
117
|
+
--json
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`--task-kind backend-test` 是选用该 DAG 的唯一方式(**不是** `--profile`)。`--verify` 命令必须取自目标项目 `AGENTS.md` / `docs/governance/verification-matrix.md` 登记的命令,不要假定 `pytest` 存在。
|
|
121
|
+
|
|
122
|
+
### 2.2 审查返回的 writeSet / gate.digest,批准并长跑
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
loop-agent task advance <task-id> \
|
|
126
|
+
--approve-gate "write-set-review:<digest>" \
|
|
127
|
+
--json
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 2.3 在 task.json 注入 jacocoCoverage(让节点 7 自动 dump)
|
|
131
|
+
|
|
132
|
+
backend-test DAG 默认**不会**收集 JaCoCo,除非任务的执行节点 shell 配置里带 `jacocoCoverage`。字段 schema 真源:`src/workflows/dag/types.ts` 的 `dagShellConfigSchema`。
|
|
133
|
+
|
|
134
|
+
在 `.harness/tasks/<task-id>/task.json` 的执行节点(`execute-backend-pytest-and-html-report-shell`)`shell` 里加:
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"id": "execute-backend-pytest-and-html-report-shell",
|
|
139
|
+
"shell": {
|
|
140
|
+
"backendTestPipeline": "markdown-execute-html",
|
|
141
|
+
"jacocoCoverage": {
|
|
142
|
+
"endpoint": "<java-service-host>:6300",
|
|
143
|
+
"cliJarPath": "/opt/jacoco/jacococli.jar",
|
|
144
|
+
"includes": "com.yourcompany.*",
|
|
145
|
+
"connectTimeoutMs": 5000
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
| 字段 | 必填 | 说明 |
|
|
152
|
+
| --- | --- | --- |
|
|
153
|
+
| `endpoint` | 是 | JaCoCo tcpserver 地址,`host:port`,**必须**与 Step 1.3 自检通过的一致 |
|
|
154
|
+
| `cliJarPath` | 是 | **backend-test 机器**上 `jacococli.jar` 的绝对路径,用于 `.exec → jacoco.xml` |
|
|
155
|
+
| `includes` | 否 | 业务包过滤,默认 `*`(**强烈建议显式指定业务包名**,与 Step 1 一致) |
|
|
156
|
+
| `connectTimeoutMs` | 否 | TCP 连接超时,默认 `5000` |
|
|
157
|
+
|
|
158
|
+
> 注入时机:若在 Step 2.1 之前注入,`task advance` 会 strict validate 时就带上;若事后补,需重新 `task advance` 触发 DAG 校验。**不要**在 DAG 执行期间修改 task.json。
|
|
159
|
+
|
|
160
|
+
### 2.4 持续监视直到终态
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
loop-agent task status <task-id> --json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
判活用可靠方式:`state.json` 的 `runner.heartbeatAt` 持续刷新 + `session-events.jsonl` 增长 + `dag doctor` 的 `liveness`,不要只靠进程过滤。主 agent 必须持续轮询直到 FINISHED / FAILED / 需要 approve,**不能**轮询一次就走。
|
|
167
|
+
|
|
168
|
+
### 2.5 产物(DAG run 目录 `.harness/dag-runs/<run-id>/` 下)
|
|
169
|
+
|
|
170
|
+
- `reports/jacoco.exec` — dump 出的执行数据
|
|
171
|
+
- `reports/jacoco.xml` — cli 转换后的 XML(**Step 3 的输入**)
|
|
172
|
+
- `contracts/code-coverage-v1.json` — runtime 解析后的归一化契约
|
|
173
|
+
- `reports/backend-test-l5-dashboard.html` — L-5 dashboard,line/branch 覆盖率已从 unavailable 变为真实数值
|
|
174
|
+
|
|
175
|
+
**BLOCKING**:进 Step 3 前确认 `reports/jacoco.xml` 存在且非空。若 Step 2.5 没有 `jacoco.xml`,说明 JaCoCo 收集降级了,按 `references/runtime-alignment.md` 的"排查清单"先修,不要带着空数据做分析。
|
|
176
|
+
|
|
177
|
+
## Step 3:结合需求文档做覆盖率切片分析
|
|
178
|
+
|
|
179
|
+
目标:把 Step 2 的 `jacoco.xml` 与需求文档对齐,产出"每个需求覆盖了哪些代码、覆盖率多少、哪些需求路径完全没被测试触达"的切片报告。
|
|
180
|
+
|
|
181
|
+
### 3.1 把需求映射成可切片的 scope(必读)
|
|
182
|
+
|
|
183
|
+
先读 `references/requirement-to-source-mapping.md`。核心约束:
|
|
184
|
+
|
|
185
|
+
- 需求 ID 必须是 `REQ-*` / `BR-*` / `AC-*` 形态(runtime 归一化器的正则要求)。PRD 里的章节标题、用户故事编号要先归一化成这三类前缀。
|
|
186
|
+
- `--source-scope` 必须是**真实存在的源码相对路径**(相对仓库根,逗号分隔)。禁止从需求文本猜路径;路径必须来自 Step 2 的 backend-test facts 或对仓库的定向事实搜索(`rg`/CodeGraph)。
|
|
187
|
+
- 一个需求 ↔ 一组源码路径的映射,是一次**可审计的决策**,不是模型自由发挥。
|
|
188
|
+
|
|
189
|
+
### 3.2 用 runtime 归一化器产出按需求切片的覆盖率
|
|
190
|
+
|
|
191
|
+
`loop-agent coverage report` 是 runtime 提供的归一化 CLI(真源 `src/commands/coverage-report.ts`、`src/workflows/dag/backend-test-coverage-contract.ts`)。它接收 `jacoco.xml` + 需求 ID + 源码 scope,输出结构化契约或 Markdown:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
loop-agent coverage report \
|
|
195
|
+
--language java \
|
|
196
|
+
--input <run-dir>/reports/jacoco.xml \
|
|
197
|
+
--requirement-id BR-CREATE-ORDER \
|
|
198
|
+
--requirement-id AC-CREATE-ORDER-001 \
|
|
199
|
+
--source-scope src/main/java/com/yourcompany/order/OrderService.java,src/main/java/com/yourcompany/order/OrderController.java \
|
|
200
|
+
--markdown \
|
|
201
|
+
--output docs/test-reports/coverage/BR-CREATE-ORDER.md
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
参数:
|
|
205
|
+
|
|
206
|
+
| 参数 | 说明 |
|
|
207
|
+
| --- | --- |
|
|
208
|
+
| `--language java` | **必须** `java`(本 skill 只处理 Java/JaCoCo) |
|
|
209
|
+
| `--input` | Step 2.5 的 `jacoco.xml`,**仓库根相对 POSIX 路径**(runtime 拒绝绝对路径:`artifact path must be a safe relative POSIX path`) |
|
|
210
|
+
| `--requirement-id` | 可重复;格式 `REQ-*`/`BR-*`/`AC-*`;来自需求文档归一化 |
|
|
211
|
+
| `--source-scope` | 逗号分隔的源码相对路径;来自事实搜索,不是猜测 |
|
|
212
|
+
| `--markdown` / `--json` | 输出格式,二选一 |
|
|
213
|
+
| `--output` | 输出文件路径;省略则打到 stdout |
|
|
214
|
+
| `--commit` / `--expected-sha256` | 可选,绑定 commit 与 artifact 指纹做审计 |
|
|
215
|
+
|
|
216
|
+
### 3.3 端到端串联(多需求批量切片)
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
bash <skill-root>/scripts/run-coverage-analysis.sh \
|
|
220
|
+
--jacoco-xml <run-dir>/reports/jacoco.xml \
|
|
221
|
+
--mapping docs/test-reports/coverage/requirement-source-mapping.json \
|
|
222
|
+
--output-dir docs/test-reports/coverage
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`requirement-source-mapping.json` 是你在 3.1 产出的映射,格式:
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"requirements": [
|
|
230
|
+
{
|
|
231
|
+
"ids": ["BR-CREATE-ORDER", "AC-CREATE-ORDER-001"],
|
|
232
|
+
"sourceScope": [
|
|
233
|
+
"src/main/java/com/yourcompany/order/OrderService.java",
|
|
234
|
+
"src/main/java/com/yourcompany/order/OrderController.java"
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"ids": ["BR-CANCEL-ORDER"],
|
|
239
|
+
"sourceScope": [
|
|
240
|
+
"src/main/java/com/yourcompany/order/OrderService.java"
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
]
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
脚本对每个需求调一次 `loop-agent coverage report`,产物落到 `--output-dir/<first-id>.md`,并生成一份汇总 `index.md`(列出每个需求的 line/branch/function 覆盖率与 `unavailable` 标记)。脚本**只调 CLI + 聚合文件**,不自己解析 XML、不算覆盖率。
|
|
248
|
+
|
|
249
|
+
### 3.4 解读与 GAP 标注
|
|
250
|
+
|
|
251
|
+
分析结论必须区分:
|
|
252
|
+
|
|
253
|
+
- **COVERED**:scope 内文件在 `jacoco.xml` 里有命中,覆盖率数值有效。
|
|
254
|
+
- **PARTIAL**:scope 内部分文件有命中、部分文件 0 命中或不在 artifact 里。
|
|
255
|
+
- **GAP**:scope 内文件完全没被任何测试触达(`jacoco.xml` 里该文件 counter 全 0 或缺失)→ 这是**测试缺口**,不是"覆盖率低",应回灌到 backend-test 的 Coverage Matrix 作为 `GAP`。
|
|
256
|
+
- **unavailable**:JaCoCo 收集本身降级(endpoint 不通、cli 缺失等)→ 先修基础设施,不要把 unavailable 当成 0% 写进报告。
|
|
257
|
+
|
|
258
|
+
## 完成规则
|
|
259
|
+
|
|
260
|
+
- Step 1 必须有 `ps`/`nc` 自检证据;Step 2 必须有 backend-test DAG 终态 + `reports/jacoco.xml` 非空证据;Step 3 每个需求的覆盖率必须来自 `loop-agent coverage report` 的真实输出,不得手写数字。
|
|
261
|
+
- 没有新鲜验证证据不声明完成;`unavailable` 必须如实标注并给出排查动作。
|
|
262
|
+
- 产物路径默认 `docs/test-reports/coverage/`;写入前确认目录与项目写入边界一致。
|
|
263
|
+
- 安全收尾:测试结束后建议关闭 Java 服务的 jacocoagent(重启服务不带 `-javaagent`),回收 `6300` 端口放行。
|
|
264
|
+
|
|
265
|
+
## 排查速查
|
|
266
|
+
|
|
267
|
+
覆盖率是 `unavailable` 或全 0?按顺序:
|
|
268
|
+
|
|
269
|
+
1. Java 服务进程参数里有没有 `jacocoagent`?(`ps aux | grep jacocoagent`)
|
|
270
|
+
2. `address` 是不是 `0.0.0.0`?端口对 backend-test 机器放行了吗?(`nc -zv <host> 6300`)
|
|
271
|
+
3. `includes` 业务包名写对了吗?(写错 → 统计到 0 个类)
|
|
272
|
+
4. `jacocoCoverage.endpoint` 与 Step 1 的 `host:port` 一致吗?
|
|
273
|
+
5. `jacocoCoverage.cliJarPath` 路径正确且 `java -jar <cli> --help` 可用吗?
|
|
274
|
+
6. agent 与 cli 版本一致吗?(都 `0.8.12`)
|
|
275
|
+
|
|
276
|
+
详见 `references/runtime-alignment.md`。
|
|
277
|
+
|
|
278
|
+
## References
|
|
279
|
+
|
|
280
|
+
- Required:`references/runtime-alignment.md`、`references/requirement-to-source-mapping.md`
|
|
281
|
+
- 项目级真源(只读引用,不复制):`docs/operations/backend-test-jacoco-coverage.md`(落地手册)、`docs/runtime/backend-test-workflow.md`(DAG 真源)、`src/workflows/dag/types.ts`(`jacocoCoverage` schema)、`src/commands/coverage-report.ts`(`coverage report` CLI)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Requirement → Source Mapping — 把需求文档对齐到覆盖率 scope
|
|
2
|
+
|
|
3
|
+
Step 3 切片分析的核心难点不是调 CLI,而是**把需求文档正确映射成 `(requirementIds, sourceScope)`**。映射错了,覆盖率数字再准也没意义。本文件给出可审计的映射纪律。
|
|
4
|
+
|
|
5
|
+
## 1. 需求 ID 归一化(BLOCKING)
|
|
6
|
+
|
|
7
|
+
runtime 归一化器只接受 `^(?:REQ|BR|AC)-[A-Z0-9]+(?:-[A-Z0-9]+)*$`(见 `runtime-alignment.md` §4)。需求文档里的原始编号通常不直接合规,必须先归一化:
|
|
8
|
+
|
|
9
|
+
| 需求文档里的写法 | 归一化结果 | 说明 |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `3.2 创建订单`(章节标题) | `BR-CREATE-ORDER` | 章节级业务规则 |
|
|
12
|
+
| `US-创建订单-001`(用户故事) | `AC-CREATE-ORDER-001` | 故事级验收标准 |
|
|
13
|
+
| `REQ-001`(已合规) | `REQ-001` | 原样 |
|
|
14
|
+
| `BR_PAYMENT_001` | `BR-PAYMENT-001` | 下划线 → 连字符 |
|
|
15
|
+
|
|
16
|
+
规则:
|
|
17
|
+
|
|
18
|
+
- 前缀三选一:`REQ`(顶层需求)/ `BR`(业务规则)/ `AC`(验收标准)。拿不准用 `BR`。
|
|
19
|
+
- body 只能是大写字母、数字、单连字符;全部大写;中文/下划线/空格先 slugify。
|
|
20
|
+
- 一个需求可挂多个 ID(如 `BR-CREATE-ORDER` + `AC-CREATE-ORDER-001`),切片时一起传。
|
|
21
|
+
|
|
22
|
+
**归一化结果必须写进 mapping 文件并回显给用户确认**,不要只在聊天里说。
|
|
23
|
+
|
|
24
|
+
## 2. sourceScope 来源(禁止臆测)
|
|
25
|
+
|
|
26
|
+
`--source-scope` 必须是**仓库里真实存在**的源码相对路径。允许的来源,按优先级:
|
|
27
|
+
|
|
28
|
+
1. **backend-test DAG facts**:Step 2 的 `contracts/backend-test-case-manifest.json` / `reports/backend-test-markdown-pytest-correspondence.md` 里映射的 pytest symbol → 生产代码路径。这是最可信来源,因为它是"本轮测试实际触达的代码"。
|
|
29
|
+
2. **定向事实搜索**:`rg` 或 CodeGraph 按需求关键词(如"创建订单")定位 controller/service 类。
|
|
30
|
+
3. **需求文档显式声明**:PRD 里如果写了"涉及 `OrderService`",可作为线索,但仍需在仓库里验证路径存在。
|
|
31
|
+
|
|
32
|
+
**禁止**:直接把需求文档里的中文术语当文件名猜路径(如把"订单服务"猜成 `OrderService.java` 而不去仓库验证)。
|
|
33
|
+
|
|
34
|
+
路径规范:
|
|
35
|
+
|
|
36
|
+
- 相对仓库根,正斜杠,逗号分隔。
|
|
37
|
+
- 不得含 `..`(runtime 会拒绝 unsafe source scope path)。
|
|
38
|
+
- 粒度到**类文件**(`.java`),不要给到包目录(runtime 按 file 过滤)。
|
|
39
|
+
|
|
40
|
+
## 3. mapping 文件格式
|
|
41
|
+
|
|
42
|
+
落到 `docs/test-reports/coverage/requirement-source-mapping.json`,与 `run-coverage-analysis.sh` 的输入一致:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"requirements": [
|
|
47
|
+
{
|
|
48
|
+
"ids": ["BR-CREATE-ORDER", "AC-CREATE-ORDER-001"],
|
|
49
|
+
"sourceScope": [
|
|
50
|
+
"src/main/java/com/yourcompany/order/OrderService.java",
|
|
51
|
+
"src/main/java/com/yourcompany/order/OrderController.java"
|
|
52
|
+
],
|
|
53
|
+
"rationale": "PRD §3.2 创建订单;pytest symbol test_create_order 映射到 OrderService.create(manifest facts)"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"ids": ["BR-CANCEL-ORDER"],
|
|
57
|
+
"sourceScope": [
|
|
58
|
+
"src/main/java/com/yourcompany/order/OrderService.java"
|
|
59
|
+
],
|
|
60
|
+
"rationale": "PRD §3.3 取消订单;仅 OrderService.cancel 被测试触达"
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`rationale` 字段是给审计用的,说明"为什么这个需求对应这些路径";脚本不消费它,但 review 时必填。
|
|
67
|
+
|
|
68
|
+
## 4. 解读覆盖率切片时的 GAP 判定
|
|
69
|
+
|
|
70
|
+
拿到 `loop-agent coverage report` 的输出后,按 `missingData` 与 counter 区分:
|
|
71
|
+
|
|
72
|
+
| 情况 | 判定 | 动作 |
|
|
73
|
+
| --- | --- | --- |
|
|
74
|
+
| scope 文件都在 artifact 里,line% > 0 | COVERED | 记录数值 |
|
|
75
|
+
| scope 文件部分在 artifact、部分不在 | PARTIAL | 标注哪些文件未命中 |
|
|
76
|
+
| scope 文件全不在 artifact(`source-scope-not-found-in-artifact`) | GAP | 测试完全没触达;回灌 backend-test Coverage Matrix 的 `GAP` |
|
|
77
|
+
| JaCoCo 收集降级(无 `jacoco.xml`) | unavailable | 先修基础设施(见 `runtime-alignment.md` §6),**不要**当 0% |
|
|
78
|
+
|
|
79
|
+
## 5. 反模式
|
|
80
|
+
|
|
81
|
+
- ❌ 把整个模块 `src/main/java/com/yourcompany/**` 塞进一个需求的 scope —— 稀释了切片意义,等于没切。
|
|
82
|
+
- ❌ 用需求文档里的业务术语当路径,不在仓库验证 —— 会得到 `source-scope-not-found-in-artifact`。
|
|
83
|
+
- ❌ 一个 source 文件只挂一个需求,但它实际服务多个需求 —— 会让多个需求覆盖率虚高。
|
|
84
|
+
- ❌ 把 `unavailable` 当 0% 写进报告 —— 误导后续决策。
|
|
85
|
+
- ❌ 用 `loop-agent coverage report` 之外的工具自己解析 `jacoco.xml` 再手填数字 —— 绕过归一化器,数字不可审计。
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Runtime Alignment — 与 loop-agent runtime 的字段与契约真源对齐
|
|
2
|
+
|
|
3
|
+
本 skill 不重新定义 runtime 字段,只把"本 skill 用到的字段"映射到 runtime 真源,避免漂移。**字段含义以本表"真源"列为准;本 skill 文档与之冲突时,以真源为准。**
|
|
4
|
+
|
|
5
|
+
## 1. backend-test DAG 的 `jacocoCoverage`(Step 2 注入字段)
|
|
6
|
+
|
|
7
|
+
| 字段 | 类型 | 必填 | 默认 | 真源 |
|
|
8
|
+
| --- | --- | --- | --- | --- |
|
|
9
|
+
| `endpoint` | `string`(`host:port`) | 是 | — | `src/workflows/dag/types.ts` `dagShellConfigSchema.jacocoCoverage.endpoint` |
|
|
10
|
+
| `cliJarPath` | `string`(绝对路径) | 是 | — | `src/workflows/dag/types.ts` `jacocoCoverage.cliJarPath` |
|
|
11
|
+
| `includes` | `string` | 否 | `*` | `src/workflows/dag/types.ts` `jacocoCoverage.includes` |
|
|
12
|
+
| `connectTimeoutMs` | `number`(正整数) | 否 | `5000` | `src/workflows/dag/types.ts` `jacocoCoverage.connectTimeoutMs` |
|
|
13
|
+
|
|
14
|
+
注入位置:task.json 的执行节点 `execute-backend-pytest-and-html-report-shell` 的 `shell` 块。该节点 pipeline 必须是 `markdown-execute-html`。
|
|
15
|
+
|
|
16
|
+
## 2. runtime 收集链路(本 skill 不重造)
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
Java 服务启动挂 jacocoagent.jar (output=tcpserver)
|
|
20
|
+
│ pytest 跑完,HTTP 请求覆盖 Java 代码
|
|
21
|
+
▼
|
|
22
|
+
backend-test 节点 7 跨网络 TCP 连 host:<port>,dump 出 reports/jacoco.exec
|
|
23
|
+
│ collectJacocoCoverage (backend-test-markdown-workflow.ts)
|
|
24
|
+
▼
|
|
25
|
+
jacococli.jar 把 .exec 转成 reports/jacoco.xml
|
|
26
|
+
│
|
|
27
|
+
▼
|
|
28
|
+
parseJacocoXml → contracts/code-coverage-v1.json (backend-test-coverage-contract.ts)
|
|
29
|
+
│
|
|
30
|
+
▼
|
|
31
|
+
computeL5ReportMetrics → reports/backend-test-l5-dashboard.html
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
真源:
|
|
35
|
+
- `src/workflows/dag/backend-test-markdown-workflow.ts` — `collectJacocoCoverage`
|
|
36
|
+
- `src/workflows/dag/backend-test-coverage-contract.ts` — `parseJacocoXml`、`readCoverageArtifact`、`formatCoverageMarkdown`
|
|
37
|
+
- `src/executors/shell-executor.ts` — 节点 7 `markdown-execute-html` pipeline
|
|
38
|
+
|
|
39
|
+
## 3. JaCoCo agent 启动参数(Step 1)
|
|
40
|
+
|
|
41
|
+
| 参数 | 取值 | 说明 |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| `output` | `tcpserver` | **必须**;默认 file 模式跨网络读不到 |
|
|
44
|
+
| `address` | `0.0.0.0` | 测试环境允许跨机器;**生产禁用** |
|
|
45
|
+
| `port` | `6300`(约定,可改) | 需与 `jacocoCoverage.endpoint` 一致 |
|
|
46
|
+
| `includes` | `<业务包>.*` | **必须改**;默认 `*` 会统计框架代码 |
|
|
47
|
+
| `append` | `false` | 每次 dump 后重置,保本轮增量 |
|
|
48
|
+
|
|
49
|
+
版本约定:agent 与 cli 都用 `0.8.12`(或同版本),版本不一致会导致 `.exec` 无法解析。
|
|
50
|
+
|
|
51
|
+
## 4. `loop-agent coverage report`(Step 3 CLI)
|
|
52
|
+
|
|
53
|
+
真源:`src/commands/coverage-report.ts`、`src/workflows/dag/backend-test-coverage-contract.ts`。
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
loop-agent coverage report \
|
|
57
|
+
--language java \
|
|
58
|
+
--input <jacoco.xml> \
|
|
59
|
+
[--requirement-id REQ-...|BR-...|AC-...] (可重复) \
|
|
60
|
+
[--source-scope path1,path2] \
|
|
61
|
+
[--commit <sha>] [--expected-sha256 <sha256>] \
|
|
62
|
+
[--tool-version <ver>] \
|
|
63
|
+
[--json|--markdown] \
|
|
64
|
+
[--output <path>]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
约束(来自 `backend-test-coverage-contract.ts` 的 zod schema):
|
|
68
|
+
|
|
69
|
+
- `--requirement-id` 正则:`^(?:REQ|BR|AC)-[A-Z0-9]+(?:-[A-Z0-9]+)*$`。不合规的 ID 会被拒绝。
|
|
70
|
+
- `--source-scope` 路径不得含 `..`(unsafe source scope path)。
|
|
71
|
+
- `--language java` 时输入必须是 JaCoCo XML;`--language python` 时输入必须是 coverage.py JSON。本 skill 只用 `java`。
|
|
72
|
+
- 输出契约字段:`sourceScope.requirementIds`、`sourceScope.paths`、line/branch/function 三类 `{ covered, missed, total, percent }`、`artifact.sha256`、`missingData[]`。
|
|
73
|
+
|
|
74
|
+
`missingData` 可能值(决定 PARTIAL/unavailable 标注):
|
|
75
|
+
|
|
76
|
+
- `source-scope-requirement-id-missing` — 没给 `--requirement-id`
|
|
77
|
+
- `source-scope-not-found-in-artifact` — `--source-scope` 的路径在 artifact 里完全找不到
|
|
78
|
+
|
|
79
|
+
## 5. 容错表(JaCoCo 收集失败安全)
|
|
80
|
+
|
|
81
|
+
来自 `docs/operations/backend-test-jacoco-coverage.md`。任一环节出错都**不阻断** pytest 与 L-5 报告:
|
|
82
|
+
|
|
83
|
+
| 失败场景 | 结果 |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `endpoint` 不通 / 端口未放行 | coverage 降级 `unavailable` |
|
|
86
|
+
| `jacococli.jar` 缺失或执行失败 | coverage 降级 `unavailable` |
|
|
87
|
+
| Java 服务没挂 agent | dump 拿到空数据,coverage 降级 `unavailable` |
|
|
88
|
+
| `jacoco.xml` 解析失败 | coverage 降级 `unavailable` |
|
|
89
|
+
| task 未配置 `jacocoCoverage` | 完全跳过,行为同未启用 |
|
|
90
|
+
|
|
91
|
+
**pytest 与 L-5 dashboard 永远不会被覆盖率收集阻断。** 因此 Step 2 的 backend-test DAG 终态可能是 FINISHED 但 `jacoco.xml` 缺失——这时进 Step 3 前必须先按排查清单修复。
|
|
92
|
+
|
|
93
|
+
## 6. 排查清单(覆盖率 unavailable / 全 0)
|
|
94
|
+
|
|
95
|
+
1. Java 服务进程是否挂了 agent?`ps aux | grep jacocoagent`
|
|
96
|
+
2. 端口是否放行?`nc -zv <host> <port>`(在 backend-test 机器上)
|
|
97
|
+
3. `address` 是否 `0.0.0.0`?(`127.0.0.1` 跨机器连不上)
|
|
98
|
+
4. `includes` 业务包名是否正确?(写错 → 0 个类)
|
|
99
|
+
5. `jacocoCoverage.cliJarPath` 是否正确且 `java -jar <cli> --help` 可用?
|
|
100
|
+
6. agent 与 cli 版本是否一致?
|
|
101
|
+
|
|
102
|
+
## 7. 安全约束
|
|
103
|
+
|
|
104
|
+
- JaCoCo agent 暴露代码执行细节,**仅限测试环境**,生产**严禁**挂载。
|
|
105
|
+
- `address=0.0.0.0` 意味着任何能访问 `<port>` 的机器都能 dump;务必用安全组限制到 backend-test 机器。
|
|
106
|
+
- `append=false` 保证每次测试数据隔离。
|