@pzy560117/codex-harness 0.1.1 → 0.1.3

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.
Files changed (31) hide show
  1. package/README.md +7 -0
  2. package/lib/powershell/find-powershell.js +17 -0
  3. package/package-source/docs/codex-harness-engineering/templates/config/agents/failure-triage.toml +4 -1
  4. package/package-source/docs/codex-harness-engineering/templates/config/agents/test-planner.toml +3 -2
  5. package/package-source/docs/codex-harness-engineering/templates/config/codex-config.toml +2 -0
  6. package/package-source/docs/codex-harness-engineering/templates/config/codex-readme.md +2 -0
  7. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/README.md +5 -2
  8. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/best-practices.md +6 -0
  9. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/examples/goal-templates.md +380 -0
  10. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/global-rules-and-bootstrap.md +16 -0
  11. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/goal-harness-integration-guide.md +364 -0
  12. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/implementation-flow.md +13 -1
  13. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/implementation-guide.md +3 -1
  14. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/codex-harness-engineering/mode-matrix.md +34 -11
  15. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/README.md +7 -0
  16. package/package-source/docs/codex-harness-engineering/templates/package-assets/docs/ecc-zh-CN/commands/e2e.md +20 -5
  17. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/harness-surface-sync/references/stale-patterns.md +3 -0
  18. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/qa-e2e-planner/SKILL.md +2 -1
  19. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/qa-e2e-runner/SKILL.md +3 -2
  20. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/qa-mock-cleaner/SKILL.md +2 -1
  21. package/package-source/docs/codex-harness-engineering/templates/package-assets/skills/speckit-e2e-tasks/SKILL.md +3 -2
  22. package/package-source/docs/codex-harness-engineering/templates/package-assets/workflows/speckit.e2e-testing.md +6 -4
  23. package/package-source/docs/codex-harness-engineering/templates/prompts/failure-triage.md +9 -7
  24. package/package-source/docs/codex-harness-engineering/templates/runtime/codex-loop.ps1 +129 -6
  25. package/package-source/docs/codex-harness-engineering/templates/runtime/doctor.ps1 +13 -1
  26. package/package-source/docs/codex-harness-engineering/templates/runtime/project-task-template.json +6 -1
  27. package/package-source/docs/codex-harness-engineering/templates/testing/e2e-plan.md +115 -14
  28. package/package-source/docs/codex-harness-engineering/templates/testing/failure-triage.md +51 -13
  29. package/package-source/install-manifest.json +1 -1
  30. package/package-source/tools/install/install-agent.ps1 +1 -0
  31. package/package.json +1 -1
@@ -18,13 +18,14 @@
18
18
 
19
19
  ## 归因规则
20
20
 
21
- 1. 先区分失败来源:spec mismatch、visual mismatch、unit、integration、e2e、build、typecheck、lint、security、environment、unknown。
22
- 2. 每个 finding 必须能追溯到具体证据路径或日志片段。
23
- 3. 合并重复 finding,避免同一根因生成多个 repair task。
24
- 4. 给出 owner:frontend、backend、test、visual-reviewer、docs、controller、environment
25
- 5. 给出推荐复验命令。
26
- 6. 无法归因时输出 `owner=controller`,并标记 `needs_human=true`。
27
- 7. 如果失败暴露了可复用风险、历史坑或排查步骤,给出 `knowledgeOutputSuggestions`,供 `ARCHIVE-*` 任务写入 `docs/knowledge/pitfalls/` 或 `guidelines/`。
21
+ 1. 先输出一级分类:`TEST_CODE_ISSUE` / `PRODUCT_BUG` / `REQUIREMENT_CHANGE` / `ENV_OR_DATA_ISSUE` / `FLAKY`。
22
+ 2. 再区分失败来源:spec mismatch、visual mismatch、unit、integration、e2e、build、typecheck、lint、security、environment、unknown。
23
+ 3. 每个 finding 必须能追溯到具体证据路径或日志片段。
24
+ 4. 合并重复 finding,避免同一根因生成多个 repair task
25
+ 5. 给出 owner:frontend、backend、test、visual-reviewer、docs、controller、environment。
26
+ 6. 给出推荐复验命令。
27
+ 7. 无法归因时输出 `owner=controller`,并标记 `needs_human=true`。
28
+ 8. 如果失败暴露了可复用风险、历史坑或排查步骤,给出 `knowledgeOutputSuggestions`,供 `ARCHIVE-*` 任务写入 `docs/knowledge/pitfalls/` 或 `guidelines/`。
28
29
 
29
30
  ## 输出格式
30
31
 
@@ -53,6 +54,7 @@
53
54
  {
54
55
  "findingId": "<task-id>-F001",
55
56
  "severity": "HIGH",
57
+ "primaryClass": "PRODUCT_BUG",
56
58
  "category": "visual_mismatch",
57
59
  "owner": "frontend",
58
60
  "evidence": ["artifacts/visual-review/<task-id>/desktop.png"],
@@ -421,15 +421,15 @@ function Get-TaskDefinitionDefaults {
421
421
  }
422
422
  "feature_plan" {
423
423
  $defaultGateProfile = "spec_required"
424
- $defaultTruthSources = @("product", "design", "testing")
424
+ $defaultTruthSources = @("product", "design", "testing", "repo_context")
425
425
  }
426
426
  "feature_impl" {
427
427
  $defaultGateProfile = "spec_required"
428
- $defaultTruthSources = @("product", "design", "plan", "testing")
428
+ $defaultTruthSources = @("product", "design", "plan", "testing", "repo_context")
429
429
  }
430
430
  "release" {
431
431
  $defaultGateProfile = "release_required"
432
- $defaultTruthSources = @("product", "design", "plan", "testing")
432
+ $defaultTruthSources = @("product", "design", "plan", "testing", "repo_context")
433
433
  }
434
434
  "archive" {
435
435
  $defaultGateProfile = "lightweight"
@@ -1766,6 +1766,116 @@ function Invoke-TestCommand {
1766
1766
  }
1767
1767
  }
1768
1768
 
1769
+ function Invoke-FailureTriage {
1770
+ <#
1771
+ 在测试失败后运行只读失败归因链路,输出结构化 triage 结果。
1772
+ #>
1773
+ param(
1774
+ [object]$Task,
1775
+ [string]$Root,
1776
+ [object]$ExecutionPolicy,
1777
+ [object]$ReviewContext,
1778
+ [object]$CodexResult,
1779
+ [object]$Stage1Result,
1780
+ [object]$TestResult,
1781
+ [string]$CodexCommand,
1782
+ [string]$LogDirectory,
1783
+ [switch]$CaptureJsonEvents
1784
+ )
1785
+
1786
+ $template = Get-PromptTemplate -Root $Root -TemplateName "failure-triage.md"
1787
+ $requirementIdsText = ConvertTo-BulletLines -Items (ConvertTo-StringArray -Value (Get-ObjectPropertyValue -InputObject $Task -Name "requirement_ids")) -EmptyText "- 未显式声明 Requirement IDs"
1788
+ $acceptanceText = ConvertTo-BulletLines -Items (ConvertTo-StringArray -Value $Task.acceptance)
1789
+ $contextFilesText = ConvertTo-BulletLines -Items $ReviewContext.task_context
1790
+ $testingText = ConvertTo-BulletLines -Items $ReviewContext.testing
1791
+ $truthSourceStateText = Convert-TruthSourceStateToBulletLines -States $ReviewContext.truth_source_state
1792
+ $triageOutputPath = Join-Path $LogDirectory "$($Task.id)-failure-triage.json"
1793
+ $testOutputPathText = if ([string]::IsNullOrWhiteSpace($TestResult.OutputLog)) { "- 无测试日志文件" } else { "- $($TestResult.OutputLog)" }
1794
+
1795
+ $prompt = @"
1796
+ $template
1797
+
1798
+ ## Driver Context
1799
+
1800
+ - Task ID: $($Task.id)
1801
+ - 描述: $($Task.description)
1802
+ - Requirement IDs:
1803
+ $requirementIdsText
1804
+ - 验收标准:
1805
+ $acceptanceText
1806
+ - 失败来源: test
1807
+ - 测试命令: $($Task.test_command)
1808
+ - 测试退出码: $($TestResult.ExitCode)
1809
+
1810
+ ### Task Context Files
1811
+ $contextFilesText
1812
+
1813
+ ### Testing Truth Sources
1814
+ $testingText
1815
+
1816
+ ### Truth Source Completeness
1817
+ $truthSourceStateText
1818
+
1819
+ ### Evidence Files
1820
+ - 实现 stdout: $($CodexResult.StdoutLog)
1821
+ - 实现 stderr: $($CodexResult.StderrLog)
1822
+ - Stage 1 stdout: $($Stage1Result.StdoutLog)
1823
+ - Stage 1 stderr: $($Stage1Result.StderrLog)
1824
+ $testOutputPathText
1825
+
1826
+ ### Raw Test Output
1827
+ ```text
1828
+ $($TestResult.Output)
1829
+ ```
1830
+
1831
+ 输出要求:
1832
+ - 只输出一个合法 JSON 对象。
1833
+ - 必须包含 findings 数组;没有 finding 也要输出空数组。
1834
+ - 优先把失败归类为 `TEST_CODE_ISSUE`、`PRODUCT_BUG`、`REQUIREMENT_CHANGE`、`ENV_OR_DATA_ISSUE` 或 `FLAKY`。
1835
+ "@
1836
+
1837
+ $triageResult = Invoke-CodexTask `
1838
+ -Prompt $prompt `
1839
+ -Root $Root `
1840
+ -Command $CodexCommand `
1841
+ -LogDirectory $LogDirectory `
1842
+ -TaskId "$($Task.id)-failure-triage" `
1843
+ -Sandbox $ExecutionPolicy.codex.review_sandbox `
1844
+ -ActivityLabel "Failure Triage" `
1845
+ -DisableHooks $ExecutionPolicy.codex.disable_hooks `
1846
+ -CaptureJsonEvents:$CaptureJsonEvents
1847
+
1848
+ $triageJson = $triageResult.Output
1849
+ if ([string]::IsNullOrWhiteSpace($triageJson)) {
1850
+ $triageJson = $triageResult.LastMessage
1851
+ }
1852
+
1853
+ $reportPath = $null
1854
+ $parseError = $null
1855
+ if (-not [string]::IsNullOrWhiteSpace($triageJson)) {
1856
+ try {
1857
+ $triageObject = $triageJson | ConvertFrom-Json -ErrorAction Stop
1858
+ $triageObject | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $triageOutputPath -Encoding UTF8
1859
+ $reportPath = $triageOutputPath
1860
+ }
1861
+ catch {
1862
+ $parseError = $_.Exception.Message
1863
+ }
1864
+ }
1865
+
1866
+ return [PSCustomObject]@{
1867
+ ExitCode = $triageResult.ExitCode
1868
+ Output = $triageResult.Output
1869
+ LastMessage = $triageResult.LastMessage
1870
+ StdoutLog = $triageResult.StdoutLog
1871
+ StderrLog = $triageResult.StderrLog
1872
+ PromptLog = $triageResult.PromptLog
1873
+ LastMessageLog = $triageResult.LastMessageLog
1874
+ ReportPath = $reportPath
1875
+ ParseError = $parseError
1876
+ }
1877
+ }
1878
+
1769
1879
  function Write-ProgressEntry {
1770
1880
  <#
1771
1881
  追加固定格式的人类可读进度记录。
@@ -2103,7 +2213,10 @@ function Invoke-OneTask {
2103
2213
  $testResult = Invoke-TestCommand -Command $task.test_command -Root $ProjectRoot -LogDirectory $taskLogDirectory -TaskId $task.id
2104
2214
 
2105
2215
  if ($testResult.ExitCode -ne 0) {
2106
- Write-ProgressEntry -Path $ProgressPath -Task $task -WorkSummary "Codex 已产生改动。" -TestSummary "测试失败,退出码 $($testResult.ExitCode)。" -Notes "禁止标记 passes=true,请人工查看 trace。" -Stage1Summary "PASS - 审查通过。" -Stage2Summary "NOT_RUN - 未进入 Stage 2 审查。"
2216
+ Write-Step "测试失败,开始自动失败归因。"
2217
+ $triageResult = Invoke-FailureTriage -Task $task -Root $ProjectRoot -ExecutionPolicy $executionPolicy -ReviewContext $reviewContext -CodexResult $codexResult -Stage1Result $stage1Result -TestResult $testResult -CodexCommand $CodexCommand -LogDirectory $taskLogDirectory -CaptureJsonEvents:$CaptureJsonEvents
2218
+ $triageNote = if ($null -ne $triageResult.ReportPath) { "failure triage: $($triageResult.ReportPath)" } elseif (-not [string]::IsNullOrWhiteSpace($triageResult.ParseError)) { "failure triage parse failed: $($triageResult.ParseError)" } else { "failure triage did not produce a structured report" }
2219
+ Write-ProgressEntry -Path $ProgressPath -Task $task -WorkSummary "Codex 已产生改动。" -TestSummary "测试失败,退出码 $($testResult.ExitCode)。" -Notes "禁止标记 passes=true,请人工查看 trace;$triageNote" -Stage1Summary "PASS - 审查通过。" -Stage2Summary "NOT_RUN - 未进入 Stage 2 审查。"
2107
2220
  $tracePayload = [PSCustomObject]@{
2108
2221
  task_id = $task.id
2109
2222
  task_session_id = $taskSessionId
@@ -2135,7 +2248,8 @@ function Invoke-OneTask {
2135
2248
  commands = @(
2136
2249
  @{ cmd = "codex exec"; exit_code = $codexResult.ExitCode },
2137
2250
  @{ cmd = "stage1 review"; exit_code = $stage1Result.ExitCode; verdict = $stage1Verdict },
2138
- @{ cmd = $task.test_command; exit_code = $testResult.ExitCode }
2251
+ @{ cmd = $task.test_command; exit_code = $testResult.ExitCode },
2252
+ @{ cmd = "failure triage"; exit_code = $triageResult.ExitCode; report = $triageResult.ReportPath }
2139
2253
  )
2140
2254
  final_message = $codexResult.Output
2141
2255
  logs = @{
@@ -2148,15 +2262,24 @@ function Invoke-OneTask {
2148
2262
  stage1_prompt = $stage1Result.PromptLog
2149
2263
  stage1_last_message = $stage1Result.LastMessageLog
2150
2264
  test_output = $testResult.OutputLog
2265
+ failure_triage_stdout = $triageResult.StdoutLog
2266
+ failure_triage_stderr = $triageResult.StderrLog
2267
+ failure_triage_prompt = $triageResult.PromptLog
2268
+ failure_triage_last_message = $triageResult.LastMessageLog
2151
2269
  }
2270
+ failure_triage_report = $triageResult.ReportPath
2271
+ failure_triage_parse_error = $triageResult.ParseError
2152
2272
  }
2153
- Add-TraceDurableFields -Trace $tracePayload -SessionDirectory $taskLogDirectory -CaptureJsonEvents:$CaptureJsonEvents -EventsSource $codexResult -LogFiles (@(Get-TraceLogFiles -CodexResults @($codexResult, $stage1Result)) + @(ConvertTo-StringArray -Value $testResult.OutputLog)) | Out-Null
2273
+ Add-TraceDurableFields -Trace $tracePayload -SessionDirectory $taskLogDirectory -CaptureJsonEvents:$CaptureJsonEvents -EventsSource $codexResult -LogFiles (@(Get-TraceLogFiles -CodexResults @($codexResult, $stage1Result, $triageResult)) + @(ConvertTo-StringArray -Value $testResult.OutputLog) + @(ConvertTo-StringArray -Value $triageResult.ReportPath)) | Out-Null
2154
2274
  Save-Trace -Directory $TracePath -Trace $tracePayload | Out-Null
2155
2275
  Write-Step "FAILED: 测试失败,退出码 $($testResult.ExitCode)。"
2156
2276
  Write-Output ""
2157
2277
  Write-Output "测试输出:"
2158
2278
  Write-Output $testResult.Output
2159
2279
  Write-Output ""
2280
+ Write-Output "Failure triage:"
2281
+ Write-Output $triageNote
2282
+ Write-Output ""
2160
2283
  Write-Output "Codex 完整日志: $($codexResult.StdoutLog)"
2161
2284
  return [PSCustomObject]@{
2162
2285
  Status = "failed"
@@ -69,7 +69,19 @@ function Add-DoctorWarning {
69
69
  function Get-DoctorFileSha256 {
70
70
  param([string]$Path)
71
71
 
72
- return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant()
72
+ $sha256 = [System.Security.Cryptography.SHA256]::Create()
73
+ $stream = $null
74
+ try {
75
+ $stream = [System.IO.File]::OpenRead($Path)
76
+ $hashBytes = $sha256.ComputeHash($stream)
77
+ return (($hashBytes | ForEach-Object { $_.ToString("x2") }) -join "")
78
+ }
79
+ finally {
80
+ if ($null -ne $stream) {
81
+ $stream.Dispose()
82
+ }
83
+ $sha256.Dispose()
84
+ }
73
85
  }
74
86
 
75
87
  function Test-TaskFileHasTemplatePlaceholder {
@@ -159,9 +159,12 @@
159
159
  },
160
160
  "steps": [
161
161
  "围绕已确认 spec 补齐页面清单、状态矩阵、边界条件、异常流和难点研究",
162
+ "先从 docs/ai/repo-map.md 或 docs/context/repo-map.md 进入代码结构,再补局部文件阅读;不要直接全仓盲扫",
162
163
  "把 Requirement IDs 映射到界面、状态、接口、测试层级、测试数据和证据路径",
164
+ "输出可复用的代码理解摘要,至少包含入口、关键调用链、受影响文件、受影响测试和高风险点",
163
165
  "把系统交付形态、公开入口、数据边界、异步边界、测试替身策略和禁止实现写入架构约束 truth source",
164
- "生成后续设计和实现必须依赖的 feature-pack、repo-map、architecture-brief 与 testing truth source"
166
+ "生成后续设计和实现必须依赖的 feature-pack、repo-map、architecture-brief 与 testing truth source",
167
+ "如果任务涉及用户可见行为、路由、表单、权限、状态流转或关键业务闭环,补齐 docs/testing/e2e-plan.md 或同等 feature 级 E2E 计划"
165
168
  ],
166
169
  "test_command": "git diff --check",
167
170
  "acceptance": [
@@ -349,6 +352,7 @@
349
352
  "把自然语言测试用例中的 TDD 候选转换为每个 feature_impl.qa_contract.tdd_contract,并保留 source_case_ids",
350
353
  "把非 TDD 自然语言用例映射到 feature_impl.qa_contract.story_full_chain.source_case_ids、acceptance_validation.source_case_ids、回归计划或 verify-matrix",
351
354
  "确认每个实现任务都已有 requirement_ids、owned_paths、context_files 和最小可行验收闭环",
355
+ "对涉及用户可见行为、路由、表单、权限、状态流转或关键业务闭环的任务,明确是否要求 docs/testing/e2e-plan.md,并把相关 E2E 命令写进 test_command 或 release 验证链路",
352
356
  "确认每个 feature_impl 任务都携带 architecture_constraints、forbidden_implementations、tdd_contract 和项目真实可执行的 test_command",
353
357
  "明确哪些故事必须串行,哪些依赖可在后续手工改成并行"
354
358
  ],
@@ -357,6 +361,7 @@
357
361
  "dev-plan、verify-matrix 和 story 级执行顺序保持一致",
358
362
  "每个 feature_impl 的 tdd_contract.red.source_case_ids 均能回溯到 NATURAL_LANGUAGE_TEST_CASES.md",
359
363
  "每个 feature_impl 的非 TDD 自然语言用例均能回溯到 story_full_chain、acceptance_validation、回归计划或 verify-matrix",
364
+ "高风险用户可见任务已经明确是否需要 e2e-plan 与对应 E2E 证据",
360
365
  "实现任务不会把测试替身、local-only adapter 或领域原型伪装成声明的交付路径",
361
366
  "后续实现与 release 任务的验证边界已经明确且可执行"
362
367
  ]
@@ -5,34 +5,135 @@
5
5
  **后端 URL**:
6
6
  **Seed 命令**:
7
7
  **测试数据计划**:
8
+ **导航入口**: `docs/ai/repo-map.md` / `docs/context/repo-map.md`
9
+ **关联代码理解摘要**:
8
10
 
9
- ## 1. 范围
11
+ ## 1. 功能概览
12
+
13
+ - 目标:
14
+ - 业务背景:
15
+ - 适用角色:
16
+ - 不覆盖范围:
17
+
18
+ ## 2. 代码入口与影响面
19
+
20
+ 先从 `repo-map` / codemap 进入,再补充局部文件阅读。不要先全仓盲扫。
21
+
22
+ | 类别 | 入口 / 文件 | 说明 | 受影响测试 |
23
+ | --- | --- | --- | --- |
24
+ | 页面 / 路由 | | | |
25
+ | 组件 | | | |
26
+ | Hook / Store / State | | | |
27
+ | API / Service | | | |
28
+ | 数据模型 / 持久化 | | | |
29
+
30
+ ## 3. 范围与角色
10
31
 
11
32
  - 范围内:
12
33
  - 范围外:
13
34
  - 必需角色:
35
+ - 权限差异:
36
+ - 登录态要求:
37
+
38
+ ## 4. 前置条件
39
+
40
+ - 环境与服务:
41
+ - Feature flag:
42
+ - 账号 / 权限:
43
+ - Seed 数据:
44
+ - 外部依赖:
45
+ - 已知豁免:
14
46
 
15
- ## 2. 主流程
47
+ ## 5. 测试数据
48
+
49
+ | 数据名称 | 用途 | 来源 | 重置方式 |
50
+ | --- | --- | --- | --- |
51
+ | 正常数据 | 主流程 | | |
52
+ | 边界数据 | 边界 / 上下限 | | |
53
+ | 非法数据 | 异常 / 权限 / 拒绝路径 | | |
54
+
55
+ ## 6. 核心主流程
16
56
 
17
57
  | ID | 角色 | 主流程 | 对应需求 | 测试数据 | 期望证据 |
18
58
  | --- | --- | --- | --- | --- | --- |
19
- | E2E-001 | 用户 | | | | 报告 + 截图 / 视频 |
59
+ | E2E-001 | 用户 | | | | 报告 + 截图 / 视频 + 状态证据 |
60
+
61
+ ## 7. 异常与边界流程
62
+
63
+ | ID | 类型 | 场景 | 预期结果 | 证据 |
64
+ | --- | --- | --- | --- | --- |
65
+ | E2E-NEG-001 | 异常 | | | |
66
+ | E2E-BND-001 | 边界 | | | |
67
+
68
+ 至少检查:
69
+
70
+ - 空数据
71
+ - 最大 / 最小输入
72
+ - 重复提交
73
+ - 网络慢
74
+ - 接口失败
75
+ - 登录过期
76
+ - 权限不足
20
77
 
21
- ## 3. 页面断言
78
+ ## 8. 页面与 UI 断言
22
79
 
23
80
  | 页面 | 状态 | 断言 | 测试层级 |
24
81
  | --- | --- | --- | --- |
25
- | | 默认 | | T5 / T6 |
82
+ | | 默认 | | T5 / T6 |
83
+ | | 错误态 | | T5 / T6 |
84
+ | | 空态 | | T5 / T6 |
85
+ | | 成功态 | | T5 / T6 |
86
+
87
+ ## 9. 接口与网络预期
88
+
89
+ | 入口动作 | 请求 | 成功预期 | 失败预期 |
90
+ | --- | --- | --- | --- |
91
+ | | `METHOD /path` | | |
92
+
93
+ ## 10. 可访问性与交互约束
94
+
95
+ - 优先使用用户可见语义定位:
96
+ - `getByRole`
97
+ - `getByLabel`
98
+ - `getByPlaceholder`
99
+ - `getByTestId`
100
+ - 避免把 DOM 层级或脆弱 CSS 选择器作为主定位手段。
101
+ - 记录关键按钮、表单标签、错误提示、loading、键盘操作和 aria 期望。
102
+
103
+ ## 11. Mock 排雷
104
+
105
+ - [ ] 从 `repo-map`、代码入口和测试目录搜索 `mock`、`fixture`、`fake`、`hardcoded`。
106
+ - [ ] P0 / P1 主流程使用真实后端或明确声明的 mock server。
107
+ - [ ] 必须 mock 的状态已在 `test-matrix.md`、`verify-matrix.md` 或豁免说明中写明。
108
+ - [ ] 前端页面如仍依赖本地假数据,先创建清理任务,再把该 E2E 标记为可执行。
109
+
110
+ ## 12. 受影响测试与执行顺序
111
+
112
+ | 类别 | 测试 / 命令 | 原因 | 优先级 |
113
+ | --- | --- | --- | --- |
114
+ | Existing | | | P0 |
115
+ | New | | | P0 |
116
+
117
+ 推荐顺序:
118
+
119
+ 1. 先跑 affected tests / contract checks。
120
+ 2. 再跑本计划对应的最小 E2E 集。
121
+ 3. 最后跑 P0 / P1 回归或跨故事整链路。
122
+
123
+ ## 13. 失败归因入口
124
+
125
+ 失败后不要直接改测试,先分类:
26
126
 
27
- ## 4. Mock 排雷
127
+ 1. 测试代码问题
128
+ 2. 产品 Bug
129
+ 3. 需求变更
130
+ 4. 环境 / 数据问题
131
+ 5. Flaky 问题
28
132
 
29
- - [ ] 搜索 `mock`、`fixture`、`fake`、`hardcoded`。
30
- - [ ] P0 主流程使用真实后端或明确的 mock server。
31
- - [ ] 必须 mock 的状态已在 `test-matrix.md` 中写明豁免。
133
+ 分类结果写入 `docs/testing/failure-triage.md` 或等价报告。
32
134
 
33
- ## 5. 失败归因
135
+ ## 14. 风险与待确认问题
34
136
 
35
- | 失败信号 | 责任方 | 下一步动作 |
36
- | --- | --- | --- |
37
- | API 返回 500 | 后端 | 创建修复任务 |
38
- | 按钮不可点击 | 前端 | 创建修复任务 |
137
+ - 高风险点:
138
+ - 未确认点:
139
+ - 需要人工验收的部分:
@@ -1,24 +1,62 @@
1
1
  # 失败归因
2
2
 
3
- | 失败类别 | 典型信号 | 归属方 | 修复目标 | 回归执行方 |
4
- | --- | --- | --- | --- | --- |
5
- | `REQ_GAP` | 缺少验收示例、业务规则含糊、没有可观察判定依据 | 产品 | 产品 / 需求负责人 | 原审查人或测试代理 |
6
- | `TRACE_GAP` | 需求未映射到 UI / API / 测试 / 证据 | requirements-trace | 追溯负责人 | 原审查人或测试代理 |
7
- | `DESIGN_GAP` | 缺少状态、选择器、交互或视觉规则 | 设计 | 设计负责人 | 原视觉 / 测试代理 |
8
- | `CONTRACT_GAP` | 缺字段、类型错误、错误码错误、鉴权规则不清楚 | 契约 | 契约负责人 | 契约测试者 |
9
- | `FRONTEND_BUG` | 按钮不可点击、路由错误、状态缺失 | 前端 | 原开发者 | 原测试代理 |
10
- | `BACKEND_BUG` | 500、业务规则错误、权限未生效 | 后端 | 后端开发者 | API 测试者 |
11
- | `TEST_BUG` | 断言错误、等待不稳定、fixture 无效或误报 | 测试 | 测试作者 | 原测试代理 |
12
- | `TEST_DATA_GAP` | 缺少 seed、账号状态错误、数据重置不可靠 | 测试 / 数据 | 测试数据负责人 | E2E 测试者 |
13
- | `ENV_BUG` | 端口冲突、服务未启动、依赖缺失 | 环境 | controller / 操作人 | test-runner |
14
- | `FLAKY` | 间歇性、非确定性失败 | test-runner | 对应 worker + 测试负责人 | 原测试代理 |
15
- | `SECURITY_RISK` | 认证、权限、密钥或敏感数据问题 | 安全 | 安全 / 后端负责人 | 安全审查者 |
3
+ ## 一级分类
4
+
5
+ 先做五选一,不要一上来就改代码或改断言。
6
+
7
+ | 一级分类 | 定义 | 允许动作 | 禁止动作 |
8
+ | --- | --- | --- | --- |
9
+ | `TEST_CODE_ISSUE` | 定位器、断言、等待时机、fixture 或测试搭建错误 | 修测试代码,保持原测试意图 | 弱化断言掩盖产品问题 |
10
+ | `PRODUCT_BUG` | 实际行为违反需求、契约或设计预期 | 输出 bug report,按 owner 修业务代码 | bug 改写成测试通过 |
11
+ | `REQUIREMENT_CHANGE` | 规格、文案、流程或契约已明确变化 | 先更新真相源,再更新测试 | 不更新规格就改测试预期 |
12
+ | `ENV_OR_DATA_ISSUE` | 服务未启动、数据不完整、权限、端口、外部依赖问题 | 修环境 / 数据并重跑 | 删除测试或直接跳过 |
13
+ | `FLAKY` | 偶发、非确定性、重跑不稳定 | 收集证据,修等待/隔离/时序 | `waitForTimeout` 掩盖问题 |
14
+
15
+ ## 二级归因
16
+
17
+ 在一级分类后,再细分 owner。
18
+
19
+ | 失败类别 | 对应一级分类 | 典型信号 | 归属方 | 修复目标 | 回归执行方 |
20
+ | --- | --- | --- | --- | --- | --- |
21
+ | `REQ_GAP` | `REQUIREMENT_CHANGE` | 缺少验收示例、业务规则含糊、没有可观察判定依据 | 产品 | 产品 / 需求负责人 | 原审查人或测试代理 |
22
+ | `TRACE_GAP` | `REQUIREMENT_CHANGE` | 需求未映射到 UI / API / 测试 / 证据 | requirements-trace | 追溯负责人 | 原审查人或测试代理 |
23
+ | `DESIGN_GAP` | `REQUIREMENT_CHANGE` | 缺少状态、选择器、交互或视觉规则 | 设计 | 设计负责人 | 原视觉 / 测试代理 |
24
+ | `CONTRACT_GAP` | `REQUIREMENT_CHANGE` | 缺字段、类型错误、错误码错误、鉴权规则不清楚 | 契约 | 契约负责人 | 契约测试者 |
25
+ | `FRONTEND_BUG` | `PRODUCT_BUG` | 按钮不可点击、路由错误、状态缺失 | 前端 | 原开发者 | 原测试代理 |
26
+ | `BACKEND_BUG` | `PRODUCT_BUG` | 500、业务规则错误、权限未生效 | 后端 | 后端开发者 | API 测试者 |
27
+ | `TEST_BUG` | `TEST_CODE_ISSUE` | 断言错误、等待不稳定、fixture 无效或误报 | 测试 | 测试作者 | 原测试代理 |
28
+ | `TEST_DATA_GAP` | `ENV_OR_DATA_ISSUE` | 缺少 seed、账号状态错误、数据重置不可靠 | 测试 / 数据 | 测试数据负责人 | E2E 测试者 |
29
+ | `ENV_BUG` | `ENV_OR_DATA_ISSUE` | 端口冲突、服务未启动、依赖缺失 | 环境 | controller / 操作人 | test-runner |
30
+ | `FLAKY` | `FLAKY` | 间歇性、非确定性失败 | test-runner | 对应 worker + 测试负责人 | 原测试代理 |
31
+ | `SECURITY_RISK` | `PRODUCT_BUG` | 认证、权限、密钥或敏感数据问题 | 安全 | 安全 / 后端负责人 | 安全审查者 |
32
+
33
+ ## 归因记录模板
34
+
35
+ ```md
36
+ ### Finding ID
37
+
38
+ - 一级分类:
39
+ - 二级分类:
40
+ - 失败测试 / 命令:
41
+ - 责任方:
42
+ - 根因:
43
+ - 证据:
44
+ - 日志:
45
+ - trace:
46
+ - screenshot / video:
47
+ - network / console:
48
+ - 修复动作:
49
+ - 重新运行结果:
50
+ - 后续验证:
51
+ ```
16
52
 
17
53
  ## 规则
18
54
 
19
55
  - 不要默认把所有失败都归给前端。
56
+ - 先从 `repo-map`、`verify-matrix`、`acceptance examples` 和相关测试计划确认预期,再判断失败性质。
20
57
  - 需求或追溯缺陷应回退给产品 / 追溯负责人,不应由实现者自行猜测修补。
21
58
  - 契约缺陷应先在契约或对应 owner 流程中修复;不要在前端 / 后端绕过问题。
22
59
  - 不要只靠代码评审就关闭 finding;应重跑最小相关测试。
23
60
  - 提出 finding 的测试者 / 审查者应在修复后负责关闭它。
24
61
  - 环境和网络失败除非超出重试预算并重复出现,否则不应视为产品失败。
62
+ - `FLAKY` 不是兜底垃圾桶;必须附带重跑结果和时序 / 隔离分析。
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": "0.1",
3
3
  "status": "draft",
4
4
  "package": "codex-harness",
5
- "version": "0.1.1",
5
+ "version": "0.1.3",
6
6
  "installModes": [
7
7
  {
8
8
  "name": "user",
@@ -2500,6 +2500,7 @@ try {
2500
2500
  Write-Output ("- 裁剪 `"{0}`" 和 `"{1}`" 为目标项目事实" -f (Join-Path $resolvedProjectRoot 'docs\ai\repo-map.md'), (Join-Path $resolvedProjectRoot 'docs\ai\architecture-brief.md'))
2501
2501
  Write-Output ("- powershell -NoProfile -ExecutionPolicy Bypass -File `"{0}`"" -f (Join-Path $resolvedProjectRoot 'tools\install\env-check.ps1'))
2502
2502
  Write-Output ("- powershell -NoProfile -ExecutionPolicy Bypass -File `"{0}`"" -f (Join-Path $resolvedProjectRoot 'tools\harness\verify.ps1'))
2503
+ Write-Output ("- 如需 7x24 长时间推进,可在 Codex app 中使用 `/goal`;推荐先读 `"{0}`" 和 `"{1}`"" -f (Join-Path $resolvedProjectRoot 'docs\codex-harness-engineering\goal-harness-integration-guide.md'), (Join-Path $resolvedProjectRoot 'docs\codex-harness-engineering\examples\goal-templates.md'))
2503
2504
  Write-Output ("- powershell -NoProfile -ExecutionPolicy Bypass -File `"{0}`"" -f (Join-Path $resolvedProjectRoot 'tools\harness\codex-loop.ps1'))
2504
2505
  }
2505
2506
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pzy560117/codex-harness",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Codex Harness installer and project runtime CLI",
5
5
  "type": "module",
6
6
  "bin": {