@tea-agent/loop-agent 0.39.0-next.31 → 0.39.0-next.33

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 (111) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/build-stamp.json +3 -3
  3. package/dist/executors/dag-pi-executor.js +7 -4
  4. package/dist/executors/pi-playwright-cli-tool.js +23 -16
  5. package/dist/executors/shell-executor.js +25 -8
  6. package/dist/shared/dag-failure-category.js +138 -0
  7. package/dist/task/config-types.js +6 -0
  8. package/dist/worker/console/chat/operation-card.js +8 -1
  9. package/dist/worker/console/chat/pi-console-config.js +81 -10
  10. package/dist/worker/console/chat/routes.js +5 -3
  11. package/dist/worker/console/inspect-split.js +18 -0
  12. package/dist/worker/console/operation-run-facts.js +19 -3
  13. package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-gauhD9kD.js → abnfDiagram-N423BO3Z-Br92EGb7.js} +1 -1
  14. package/dist/worker/console/static/assets/{arc-pm3c2Rsl.js → arc-oulImtQq.js} +1 -1
  15. package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-D_JAg3wH.js → architectureDiagram-T3A2C74G-tyHc6aqO.js} +1 -1
  16. package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-Dk7-ex52.js → blockDiagram-VBNYF7ZC-CY86BSpT.js} +1 -1
  17. package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-Uval9oRI.js → c4Diagram-5PPSVZJV-BKKsDmNs.js} +1 -1
  18. package/dist/worker/console/static/assets/channel-TY36zt-i.js +1 -0
  19. package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-BSYjHs-v.js → chunk-2GRJ4B5K-CXZdjl3B.js} +1 -1
  20. package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-KGUuBXI8.js → chunk-2Q5K7J3B-B-aIFDQ5.js} +1 -1
  21. package/dist/worker/console/static/assets/{chunk-5RXB4S5H-JqAtxD9N.js → chunk-5RXB4S5H-BDgAW_B2.js} +1 -1
  22. package/dist/worker/console/static/assets/{chunk-5VM5RSS4-D6EJOVQK.js → chunk-5VM5RSS4-DABa4UPR.js} +1 -1
  23. package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-B1JriSjm.js → chunk-6Q2QTUOP-aGbysVOx.js} +1 -1
  24. package/dist/worker/console/static/assets/{chunk-GF5L2VYU-D62b96Jd.js → chunk-GF5L2VYU-B8MSZDVs.js} +1 -1
  25. package/dist/worker/console/static/assets/{chunk-JWPE2WC7-BsNKEC_r.js → chunk-JWPE2WC7-CpelV73g.js} +1 -1
  26. package/dist/worker/console/static/assets/{chunk-KBJHAD2P-B56v6-ZP.js → chunk-KBJHAD2P-BE04ty3z.js} +1 -1
  27. package/dist/worker/console/static/assets/{chunk-RYQCIY6F-D2KPnd8K.js → chunk-RYQCIY6F-BUxTkaaR.js} +1 -1
  28. package/dist/worker/console/static/assets/{chunk-XXDRQBXY-kzKSCaaL.js → chunk-XXDRQBXY-CYYBVKfX.js} +1 -1
  29. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-Dk7QCChM.js +1 -0
  30. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-Dk7QCChM.js +1 -0
  31. package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-C6N6KNJd.js → cose-bilkent-JH36ORCC-CEQF_xmQ.js} +1 -1
  32. package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-DiyymT2D.js → cynefin-VYW2F7L2-CqpxN5IT.js} +1 -1
  33. package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-BeKAXvf3.js → cynefinDiagram-MW4NZA55-B3PzanVi.js} +1 -1
  34. package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-TkIdXfPF.js → dagre-VZM6K2ZE-BSUGCNx1.js} +1 -1
  35. package/dist/worker/console/static/assets/{diagram-7IWD3JNH-BFmSG3ks.js → diagram-7IWD3JNH-CdLevU5T.js} +1 -1
  36. package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-DqpJT2Fs.js → diagram-B4RE2ZJO-BjpF_Kok.js} +1 -1
  37. package/dist/worker/console/static/assets/{diagram-LBJQPF4R-r5ATN43t.js → diagram-LBJQPF4R-C4I6NJny.js} +1 -1
  38. package/dist/worker/console/static/assets/{diagram-Q27KOJAE-DEcSCMuR.js → diagram-Q27KOJAE-C8hecCr5.js} +1 -1
  39. package/dist/worker/console/static/assets/{diagram-UB23O5K3-VOvYRLVc.js → diagram-UB23O5K3-Daod6tOS.js} +1 -1
  40. package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-D7f4Cb1u.js → ebnfDiagram-BXEA7PRR-BvvmazGv.js} +1 -1
  41. package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-ziUf3U0G.js → erDiagram-JOGREHBK-DeN_vfV4.js} +1 -1
  42. package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-BoRdQ-1y.js → flowDiagram-UKHOOZJN-D6dq1t9z.js} +1 -1
  43. package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-B1-GncNm.js → ganttDiagram-PKOTCBZU-DziIdNY4.js} +1 -1
  44. package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-CTW-ph8W.js → gitGraphDiagram-DS77QQ5N-Dy4s5CXr.js} +1 -1
  45. package/dist/worker/console/static/assets/index-C3GgHg-g.css +1 -0
  46. package/dist/worker/console/static/assets/index-Ci8ksvBm.js +406 -0
  47. package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BFA337tZ.js → infoDiagram-6WML65LV-Czv5eYx2.js} +1 -1
  48. package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BtEujgRR.js → ishikawaDiagram-WSZJBQD7-Bsk3nFRT.js} +1 -1
  49. package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-C8ZwD2Jp.js → journeyDiagram-NVQOT4AX-DxGmNj5K.js} +1 -1
  50. package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-Ck-z8B11.js → kanban-definition-27J2QSJJ-CYCFqkO_.js} +1 -1
  51. package/dist/worker/console/static/assets/{linear-CAyXjQjN.js → linear-B0YzRwrd.js} +1 -1
  52. package/dist/worker/console/static/assets/{mermaid.core-CcWKn6tS.js → mermaid.core-t3EZtIGh.js} +5 -5
  53. package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-C2NuDO7E.js → mindmap-definition-FAOFIHXS-BTXpTv0T.js} +1 -1
  54. package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BFub3PDz.js → pegDiagram-VL7TDLO6-DU8UkKqA.js} +1 -1
  55. package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BJx5THZ5.js → pieDiagram-7S7Q4E2Y-DP4y8ohp.js} +1 -1
  56. package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-DhalkDWV.js → quadrantDiagram-CIZ2JOQS-B07vNaYR.js} +1 -1
  57. package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-CVcBM36o.js → railroadDiagram-AXF67PYL-xDWktb2i.js} +1 -1
  58. package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D_vy4n0w.js → requirementDiagram-LRYGKXZP-BLNMKqeS.js} +1 -1
  59. package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DGYdJL1D.js → sankeyDiagram-W5VNT64P-n0adalxH.js} +1 -1
  60. package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-C1xJFg3k.js → sequenceDiagram-SI44F4Z6-BbnS-2DL.js} +1 -1
  61. package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-D_Fc43df.js → sizeCapture-X5ZJPWSS-B4uPpCLu.js} +1 -1
  62. package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BhGbIjbu.js → stateDiagram-OKZ733FA--MMbB0fX.js} +1 -1
  63. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BqOigMQ4.js +1 -0
  64. package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-DVkNcO-V.js → swimlanes-SLNWSIFB-BXUgp2QY.js} +2 -2
  65. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-Caxz9UA2.js +8 -0
  66. package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-BQU9ufV0.js → timeline-definition-Z64GVDOM-CsaMxki7.js} +1 -1
  67. package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-BCQhRmYB.js → vennDiagram-T6HMQDX7-C2IuG9iH.js} +1 -1
  68. package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DWerOyHO.js → wardleyDiagram-T6FBY63Y-CmEWOXCW.js} +1 -1
  69. package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-DxLeebQU.js → xychartDiagram-ELKLHX3M-D_9LE0MG.js} +1 -1
  70. package/dist/worker/console/static/index.html +2 -2
  71. package/dist/worker/console/static-src/app/useRecoveryConsole.js +38 -2
  72. package/dist/worker/console/static-src/app/useRunProgress.js +46 -0
  73. package/dist/worker/console/static-src/operator-chat/cards/failure-category-advice.js +25 -0
  74. package/dist/worker/console/static-src/operator-chat/input-history.js +76 -0
  75. package/dist/worker/console/static-src/operator-chat/turn-submission.js +13 -1
  76. package/dist/worker/console/static-src/operator-chat/useChatStream.js +29 -9
  77. package/dist/worker/console/static-src/operator-chat/useComposer.js +32 -0
  78. package/dist/worker/console/static-src/pages/tasks/run-id-resolution.js +79 -0
  79. package/dist/worker/console/static-src/pages/tasks/run-ownership-verify.js +23 -0
  80. package/dist/worker/console/static-src/pages/tasks/run-panel-progress.js +110 -0
  81. package/dist/worker/materialize/harness-task-lineage.js +5 -2
  82. package/dist/worker/observability/read-model.js +22 -0
  83. package/dist/workflows/dag/dynamic-runtime/loop-until.js +1 -1
  84. package/dist/workflows/dag/dynamic-runtime/map.js +1 -1
  85. package/dist/workflows/dag/failure-category.js +7 -128
  86. package/dist/workflows/dag/frontend-test-case-checklist.js +4 -2
  87. package/dist/workflows/dag/frontend-test-case-manifest.js +6 -4
  88. package/dist/workflows/dag/frontend-test-case-quality.js +6 -3
  89. package/dist/workflows/dag/frontend-test-environment-probe.js +10 -7
  90. package/dist/workflows/dag/frontend-test-html-report.js +3 -1
  91. package/dist/workflows/dag/frontend-test-l5-report.js +3 -1
  92. package/dist/workflows/dag/frontend-test-layout.js +159 -0
  93. package/dist/workflows/dag/frontend-test-result-contract.js +28 -14
  94. package/dist/workflows/dag/frontend-test-standard-scenarios.js +3 -1
  95. package/dist/workflows/dag/init-hybrid.js +58 -13
  96. package/dist/workflows/dag/types.js +12 -0
  97. package/dist/workflows/dag/validate.js +23 -19
  98. package/docs/templates/frontend-test-case-checklist.md +2 -2
  99. package/harness.json +3 -3
  100. package/package.json +1 -1
  101. package/skills/fe-test-ui-scout/SKILL.md +4 -4
  102. package/skills/fe-test-ui-scout/references/ledger-schema.md +1 -1
  103. package/skills/playwright-cli/SKILL.md +1 -1
  104. package/skills/playwright-cli-case-generator/SKILL.md +10 -8
  105. package/dist/worker/console/static/assets/channel-CVrnUdZl.js +0 -1
  106. package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-aX91WTya.js +0 -1
  107. package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-aX91WTya.js +0 -1
  108. package/dist/worker/console/static/assets/index-C8rOIAJr.css +0 -1
  109. package/dist/worker/console/static/assets/index-DEbyrEfW.js +0 -404
  110. package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DUt1lyFL.js +0 -1
  111. package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BM6SGr7j.js +0 -8
@@ -5,6 +5,7 @@ import { resolveRepairTaskForGate } from "./repair-artifact.js";
5
5
  import { topoSortToRanks } from "./topo.js";
6
6
  import { isSafeReadOnlyPiRetryCandidate, isWriterEmptyDiffRetryCandidate, isWriterTransportRetryCandidate, INCOMPLETE_WRITE_SET_RETRY_CATEGORY, WRITER_CLEAN_TIMEOUT_RETRY_CATEGORY, WRITER_EMPTY_DIFF_RETRY_CATEGORY, } from "./retry-policy.js";
7
7
  import { isBackendTestCompletenessRetryCandidate } from "./backend-test-writer-completeness.js";
8
+ import { defaultFrontendTestLayout, frontendTestLayoutFromSpec, } from "./frontend-test-layout.js";
8
9
  const GOVERNANCE_WARNING_TYPES = new Set([
9
10
  "read-only-missing-artifacts-forbidden",
10
11
  "read-only-prompt-mentions-artifact-writes",
@@ -680,22 +681,23 @@ function validateWriterOutcomePolicyTaskConfig(task, issues) {
680
681
  });
681
682
  }
682
683
  }
683
- function isFrontendEvidenceWriteSet(writeSet) {
684
+ function isFrontendEvidenceWriteSet(writeSet, layout = defaultFrontendTestLayout()) {
684
685
  const entries = writeSet ?? [];
685
686
  if (entries.length === 0)
686
687
  return false;
688
+ const prefix = `${layout.evidenceDir}/`;
689
+ const glob = `${layout.evidenceDir}/**`;
687
690
  return entries.every((entry) => {
688
691
  const normalized = entry.trim().replace(/\\/g, "/").replace(/^\.\//, "");
689
- return (normalized === "testcase/frontend/evidence/**" ||
690
- normalized.startsWith("testcase/frontend/evidence/"));
692
+ return normalized === glob || normalized.startsWith(prefix);
691
693
  });
692
694
  }
693
- function isFrontendBrowserExecutorTask(task) {
695
+ function isFrontendBrowserExecutorTask(task, layout = defaultFrontendTestLayout()) {
694
696
  const skills = task.skills ?? [];
695
697
  return (task.executor === "pi" &&
696
698
  task.toolProfile === "write" &&
697
699
  skills.includes("playwright-cli") &&
698
- isFrontendEvidenceWriteSet(task.writeSet));
700
+ isFrontendEvidenceWriteSet(task.writeSet, layout));
699
701
  }
700
702
  function taskMentionsPlaywrightCliContract(task) {
701
703
  const prompt = `${task.subtask_prompt}\n${task.outputContract ?? ""}`;
@@ -707,10 +709,11 @@ function taskMentionsPlaywrightCliContract(task) {
707
709
  * - capability is granted without skill/prompt contract or outside evidence writeSet
708
710
  * - non-browser nodes receive command capability
709
711
  */
710
- function validateCommandPolicyTaskConfig(task, issues) {
712
+ function validateCommandPolicyTaskConfig(task, issues, spec) {
713
+ const layout = frontendTestLayoutFromSpec(spec);
711
714
  const policy = resolveDagCommandPolicy(task.commandPolicy);
712
715
  const allowsPlaywright = dagCommandPolicyAllows(task.commandPolicy, "playwright-cli");
713
- const isBrowserExecutor = isFrontendBrowserExecutorTask(task);
716
+ const isBrowserExecutor = isFrontendBrowserExecutorTask(task, layout);
714
717
  if (isBrowserExecutor && !allowsPlaywright) {
715
718
  issues.push({
716
719
  type: "invalid-command-policy",
@@ -741,10 +744,10 @@ function validateCommandPolicyTaskConfig(task, issues) {
741
744
  message: `task ${task.id} playwright-cli command capability requires prompt/outputContract to reference playwright_cli`,
742
745
  });
743
746
  }
744
- if (!isFrontendEvidenceWriteSet(task.writeSet)) {
747
+ if (!isFrontendEvidenceWriteSet(task.writeSet, layout)) {
745
748
  issues.push({
746
749
  type: "invalid-command-policy",
747
- message: `task ${task.id} playwright-cli command capability requires frontend evidence writeSet under testcase/frontend/evidence/`,
750
+ message: `task ${task.id} playwright-cli command capability requires frontend evidence writeSet under ${layout.evidenceDir}/`,
748
751
  });
749
752
  }
750
753
  if (task.toolProfile !== "write") {
@@ -755,7 +758,7 @@ function validateCommandPolicyTaskConfig(task, issues) {
755
758
  }
756
759
  }
757
760
  }
758
- function validateDynamicChildCommandPolicy(task, issues) {
761
+ function validateDynamicChildCommandPolicy(task, issues, spec) {
759
762
  const expansion = task.dynamicExpansion;
760
763
  if (!expansion)
761
764
  return;
@@ -776,7 +779,7 @@ function validateDynamicChildCommandPolicy(task, issues) {
776
779
  writeSet: child.writeSet,
777
780
  outputContract: child.outputContract,
778
781
  };
779
- validateCommandPolicyTaskConfig(synthetic, issues);
782
+ validateCommandPolicyTaskConfig(synthetic, issues, spec);
780
783
  }
781
784
  function validateDecisionGateTaskConfig(task, issues) {
782
785
  if (!task.decisionGate?.enabled) {
@@ -883,12 +886,13 @@ export function collectForbiddenExecutorIssues(spec, forbiddenExecutors) {
883
886
  }));
884
887
  }
885
888
  /** Revalidate a rendered dynamic child before it enters state or executes. */
886
- export function assertValidMaterializedDagTask(task) {
889
+ export function assertValidMaterializedDagTask(task, parentSpec) {
887
890
  const issues = [];
888
- // A minimal v2 carrier makes write-policy validation strict while avoiding
889
- // unrelated parent graph/rank checks. Dynamic templates are validated at
890
- // init; this guards values introduced by {{item}} rendering.
891
- const spec = { version: 2, tasks: [task] };
891
+ const spec = {
892
+ version: 2,
893
+ tasks: [task],
894
+ frontendTestLayout: parentSpec?.frontendTestLayout,
895
+ };
892
896
  validateTaskWritePolicy(task, spec, issues);
893
897
  validateShellTaskConfig(task, spec, issues);
894
898
  validateStaticTaskConfig(task, issues);
@@ -896,7 +900,7 @@ export function assertValidMaterializedDagTask(task) {
896
900
  validateRetryPolicyTaskConfig(task, issues);
897
901
  validateOutputProtocolTaskConfig(task, issues);
898
902
  validateWriterOutcomePolicyTaskConfig(task, issues);
899
- validateCommandPolicyTaskConfig(task, issues);
903
+ validateCommandPolicyTaskConfig(task, issues, spec);
900
904
  if (issues.length > 0) {
901
905
  throw new Error(`invalid materialized dynamic child ${task.id}: ${issues.map((issue) => issue.message).join("; ")}`);
902
906
  }
@@ -952,8 +956,8 @@ export function validateDagSpec(spec) {
952
956
  validateRetryPolicyTaskConfig(task, issues);
953
957
  validateOutputProtocolTaskConfig(task, issues);
954
958
  validateWriterOutcomePolicyTaskConfig(task, issues);
955
- validateCommandPolicyTaskConfig(task, issues);
956
- validateDynamicChildCommandPolicy(task, issues);
959
+ validateCommandPolicyTaskConfig(task, issues, spec);
960
+ validateDynamicChildCommandPolicy(task, issues, spec);
957
961
  validateProjectGovernanceTaskConfig(task, spec, issues);
958
962
  validatePiExtensionsTaskConfig(task, issues);
959
963
  validateFailureAwareDependsOn(task, spec, issues);
@@ -15,7 +15,7 @@ LLM review (when `frontendTest.reviewMode=blocking`) must not invent blocking ru
15
15
  | `unknown-ac` | When task `sourceBinding.requirementIds` lists ACs, every `acIds` entry must be in that set |
16
16
  | `case-id-shape` | `caseId` matches `FE-<FEATURE>-<NNN>-...` (never `AC-FE-*`) |
17
17
  | `case-id-is-ac` | Do not use acceptance id as `caseId` / filename |
18
- | `case-path-mismatch` | `casePath === testcase/frontend/cases/{caseId}.md` |
18
+ | `case-path-mismatch` | `casePath === {casesDir}/{caseId}.md`(默认 `testcase/frontend/cases/{caseId}.md`) |
19
19
  | `case-file-missing` | `casePath` exists |
20
20
 
21
21
  ## Tool guidance (non-blocking)
@@ -40,5 +40,5 @@ LLM review (when `frontendTest.reviewMode=blocking`) must not invent blocking ru
40
40
 
41
41
  ## Pipeline vs quality
42
42
 
43
- - **Pipeline acceptance**: final `testcase/frontend/reports/frontend-test-retrospect-*.md` exists after result materialize
43
+ - **Pipeline acceptance**: final `{reportsDir}/frontend-test-retrospect-*.md` exists after result materialize (default `testcase/frontend/reports/`)
44
44
  - **Quality**: `frontend-test-result-v1.outcome=passed` with 0 blocked/failed (opt-in via `frontendTest.strictOutcomeGate`)
package/harness.json CHANGED
@@ -82,9 +82,9 @@
82
82
  "executors": {
83
83
  "pi": {
84
84
  "description": "Pi 负责规划、评审、诊断;当 DAG toolProfile=write 时也可做有界写入。模型按复杂度三档配置,支持 provider/model 字符串或带 thinking 的对象;斜杠前为 Pi provider,后为 modelId,勿只写裸 modelId。",
85
- "LOW": "wizard-local/minimax-m3",
86
- "MED": "wizard-local/minimax-m3",
87
- "HIGH": "wizard-local/minimax-m3"
85
+ "LOW": "deepseek/deepseek-v4-flash",
86
+ "MED": "deepseek/deepseek-v4-flash",
87
+ "HIGH": "deepseek/deepseek-v4-flash"
88
88
  }
89
89
  }
90
90
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tea-agent/loop-agent",
3
- "version": "0.39.0-next.31",
3
+ "version": "0.39.0-next.33",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "loop-agent": "bin/loop-agent.js",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: fe-test-ui-scout
3
- description: 在写 frontend-test Wave PRD/回归目录之前,对真实运行的被测页面做只读锚点侦察,产出并维护 testcase/frontend/rag/ui-anchors.md 锚点台账。用 playwright-cli snapshot/find 逐字面验证命中数与唯一性,防止 PRD 验收标准引用不存在或不唯一的文案。触发词:frontend-test、锚点、台账、ui-anchors、侦察、写 PRD 前、snapshot/find 校准、Wave PRD。
3
+ description: 在写 frontend-test Wave PRD/回归目录之前,对真实运行的被测页面做只读锚点侦察,产出并维护 {testRoot}/rag/ui-anchors.md 锚点台账(默认 testcase/frontend/rag/ui-anchors.md)。用 playwright-cli snapshot/find 逐字面验证命中数与唯一性,防止 PRD 验收标准引用不存在或不唯一的文案。触发词:frontend-test、锚点、台账、ui-anchors、侦察、写 PRD 前、snapshot/find 校准、Wave PRD。
4
4
  references:
5
5
  - path: references/ledger-schema.md
6
6
  required: true
@@ -13,7 +13,7 @@ references:
13
13
  ## 定位
14
14
 
15
15
  写 Wave PRD / 校准回归目录 AC **之前**的前置侦察。产出锚点台账
16
- `testcase/frontend/rag/ui-anchors.md`:每个「页面 × 状态」下真实可见、
16
+ `{testRoot}/rag/ui-anchors.md`(默认 `testcase/frontend/rag/ui-anchors.md`):每个「页面 × 状态」下真实可见、
17
17
  `find` 可命中的字面清单。PRD 的每条 `find "..."` 断言必须能在台账找到对应行;
18
18
  台账没有的字面禁止写进验收标准。
19
19
 
@@ -23,7 +23,7 @@ references:
23
23
 
24
24
  ## 输入
25
25
 
26
- - 被测 baseUrl(来自 `testcase/frontend/rag/context.md` 的 `environmentProbe=reachable` URL)
26
+ - 被测 baseUrl(来自 `{testRoot}/rag/context.md` 的 `environmentProbe=reachable` URL;默认 `testcase/frontend/rag/context.md`)
27
27
  - 目标 Wave 的 AC 清单(回归目录中本 Wave 范围的行)
28
28
  - 既有台账(增量更新,不整表重写)
29
29
 
@@ -56,7 +56,7 @@ references:
56
56
 
57
57
  ## 输出
58
58
 
59
- - `testcase/frontend/rag/ui-anchors.md`(增量更新)
59
+ - `{testRoot}/rag/ui-anchors.md`(增量更新;默认 `testcase/frontend/rag/ui-anchors.md`)
60
60
  - 侦察小结(对话内输出,不落盘;结论回写 PRD 草稿的锚点引用)
61
61
 
62
62
  ## References
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 文件位置与命名
4
4
 
5
- - 路径:`testcase/frontend/rag/ui-anchors.md`
5
+ - 路径:`{testRoot}/rag/ui-anchors.md`(默认 `testcase/frontend/rag/ui-anchors.md`)
6
6
  - 编码:UTF-8,LF;表格用 GitHub Flavored Markdown。
7
7
  - 台账是**增量账本**:修订不删除历史行;失效行改状态列并注明原因。
8
8
 
@@ -55,7 +55,7 @@ request
55
55
 
56
56
  ## 推荐执行流程
57
57
 
58
- 使用 `testcase/frontend/rag/context.md` 中已由 environment shell 标记为 `reachable` 的非生产 `baseUrl` 和默认浏览器 session;不得创建 named session。交互前先获取 snapshot,并只使用 snapshot 中可见的 ref 或已知安全 locator。
58
+ 使用 `{testRoot}/rag/context.md`(默认 `testcase/frontend/rag/context.md`)中已由 environment shell 标记为 `reachable` 的非生产 `baseUrl` 和默认浏览器 session;不得创建 named session。交互前先获取 snapshot,并只使用 snapshot 中可见的 ref 或已知安全 locator。截图写入当前 case 的 `{evidenceDir}/<caseId>/`,canonical 文件名仍是 `final.png`。
59
59
 
60
60
  ```text
61
61
  playwright-cli open --browser=chrome http://localhost:5173
@@ -13,10 +13,12 @@ description: 根据 FE-test RAG 知识包生成可由受限 playwright_cli runti
13
13
 
14
14
  ## 输入与边界
15
15
 
16
- - 只读取 `testcase/frontend/rag/context.md`、`coverage-map.md` 与已有 `testcase/frontend/cases/`。
17
- - 若存在 `testcase/frontend/rag/ui-anchors.md` 锚点台账,必须一并读取并作为 UI 断言的唯一事实源;台账缺失时按 RAG 知识包生成,但不得引用台账外的具体控件字面(缺失信息标 `blocked`)。
18
- - 只写 `testcase/frontend/cases/**`;不得回读 PRD、读取 `.harness/`,或写
19
- `testcase/frontend/evidence/**`。
16
+ 默认产物根是 `testcase/frontend/`。若任务配置了 `frontendTest.testRoot`,把下列路径中的 `testcase/frontend/` 整段替换为该根(不要只替换 `testcase/`)。
17
+
18
+ - 只读取 `{testRoot}/rag/context.md`、`coverage-map.md` 与已有 `{testRoot}/cases/`。
19
+ - 若存在 `{testRoot}/rag/ui-anchors.md` 锚点台账,必须一并读取并作为 UI 断言的唯一事实源;台账缺失时按 RAG 知识包生成,但不得引用台账外的具体控件字面(缺失信息标 `blocked`)。
20
+ - 只写 `{testRoot}/cases/**`;不得回读 PRD、读取 `.harness/`,或写
21
+ `{testRoot}/evidence/**`。
20
22
  - 所有 API、字段限制、状态流转、数据来源、SLA、URL 与账号要求必须能在 RAG 知识包中追溯。
21
23
  缺失信息标记 `blocked` 或“需人工确认”,不得猜测。
22
24
 
@@ -38,10 +40,10 @@ description: 根据 FE-test RAG 知识包生成可由受限 playwright_cli runti
38
40
  (例:`FE-LOGIN-001-core`)。禁止把验收标准写成 caseId。
39
41
  - `acIds` = **验收标准 ID 列表**,形态 `AC-FE-*` / `AC-*`
40
42
  (例:`["AC-FE-001"]`)。禁止把用例 ID 放进 acIds。
41
- - `casePath` 必须等于 `testcase/frontend/cases/<caseId>.md`;
42
- `evidenceDir` 必须等于 `testcase/frontend/evidence/<caseId>/`。
43
+ - `casePath` 必须等于 `{casesDir}/<caseId>.md`(默认 `testcase/frontend/cases/<caseId>.md`);
44
+ `evidenceDir` 必须等于 `{evidenceDir}/<caseId>/`(默认 `testcase/frontend/evidence/<caseId>/`)。
43
45
  - `manifest` 使用 `schemaVersion: 1`,每项只含 `caseId`、`casePath`、`dimension`、`acIds`、
44
- `evidenceDir`。所有 ID、路径和 evidenceDir 必须唯一,并位于 `testcase/frontend/` 内。
46
+ `evidenceDir`。所有 ID、路径和 evidenceDir 必须唯一,并位于 `{testRoot}/` 内。
45
47
  - `index.md` 按功能点列出 case、维度、AC、数据依赖、API 映射和预期执行状态。
46
48
 
47
49
  每个 case 必须包含:
@@ -73,7 +75,7 @@ description: 根据 FE-test RAG 知识包生成可由受限 playwright_cli runti
73
75
  7. 明确的 UI/API 预期与数据清理结果;无法满足的环境或数据依赖必须写为 `blocked`。
74
76
 
75
77
  所有文件型输出均由 controller 绑定到执行节点提供的
76
- `testcase/frontend/evidence/<case-id>/` 工作目录。截图一律使用 canonical 语法
78
+ `{evidenceDir}/<case-id>/` 工作目录(默认 `testcase/frontend/evidence/<case-id>/`)。截图一律使用 canonical 语法
77
79
  `playwright-cli screenshot --filename final.png`;如确有从最新 snapshot 解析出的真实元素 ref,写为
78
80
  `playwright-cli screenshot e5 --filename final.png`。`pdf` 必须写为
79
81
  `playwright-cli pdf --filename final.pdf`。`snapshot` 无 filename 时仅返回响应;需要文件时使用
@@ -1 +0,0 @@
1
- import{ag as o,ah as n}from"./mermaid.core-CcWKn6tS.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-D62b96Jd.js";import{_ as i}from"./mermaid.core-CcWKn6tS.js";import"./chunk-5VM5RSS4-D6EJOVQK.js";import"./chunk-XXDRQBXY-kzKSCaaL.js";import"./chunk-KBJHAD2P-B56v6-ZP.js";import"./chunk-2GRJ4B5K-BSYjHs-v.js";import"./index-DEbyrEfW.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-GF5L2VYU-D62b96Jd.js";import{_ as i}from"./mermaid.core-CcWKn6tS.js";import"./chunk-5VM5RSS4-D6EJOVQK.js";import"./chunk-XXDRQBXY-kzKSCaaL.js";import"./chunk-KBJHAD2P-B56v6-ZP.js";import"./chunk-2GRJ4B5K-BSYjHs-v.js";import"./index-DEbyrEfW.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};